Помогите понять макросы C stdarg (va_start ...) - PullRequest
0 голосов
/ 19 июля 2010

недавно я наткнулся на эту функцию (используется в классе регистратора). Я понимаю что делает, но я не знаю как :

void Reporter::print( const char* szFormat, ...)
{
    // note: m_out is a FILE*
    va_list args;
    va_start(args, szFormat);
    vfprintf( m_out, szFormat, args);
    va_end(args);
}

Я прочитал ссылку , но мне все еще неясно. Больше всего меня беспокоит то, что это работает не так, как ожидалось. Я получаю 0 для последнего числа и (ноль) для строки, хотя она должна вывести некоторое число больше 0 и путь к файлу.

Дело 1:

rep.print( "Values: %08X %08X %08X %08X %08X %08X %d %s\n", val1, val2, val3, val4, val5, val6, source.GetLength(), szPath );
// source.GetLength() returns a size_t, szPath is a const char* and IS indeed a valid string

Но если изменить его на это, то работает нормально:

Дело 2:

rep.print( "Values: %08X %08X %08X %08X %08X %08X", val1, val2, val3, val4, val5, val6 );
rep.print( " %d %s\n", source.GetLength(), szPath );

Обратите внимание, что я компилирую под MSVC ++ 2008. Тот же код работает нормально (даже в первом случае) под gcc. Есть ли ошибка в реализации Reporter :: print () или в том, как я использую функцию? Как я могу убедиться, что он будет работать нормально даже при вызове, как в первом случае? И почему он вообще терпит неудачу?

1 Ответ

3 голосов
/ 19 июля 2010

Код для Reporter::print в порядке.Все, что он делает, это правильно инициализирует args для ссылки на список переменных-переменных, а затем передает этот список переменных-переменных на vfprintf(), который знает, что с ним делать.

Ваша проблема, вероятно,Спецификатор формата %d (для которого требуется аргумент типа int) не соответствует типу значения, возвращаемого source.GetLength() (что, я бы предположил, может быть size_t).Если вы знаете, что длина всегда будет вписываться в int, то вы можете решить ее с помощью преобразования приведения:

..., (int)source.GetLength(), ...

(это так, потому что ожидаемый тип аргументов, являющихся частью переменнойсписок аргументов не известен компилятору, в отличие от обычного объявления функции прототипа).

...