Как использовать атрибут GCC 'format'?
Вот небольшой фрагмент кода:
#include <stdio.h>
#include <stdarg.h>
void MyPrintf(char const* format, va_list args);
void MyVariadicPrintf(char const* format, ...);
void MyPrintf(char const* format, va_list args)
{
vprintf(format, args);
}
void MyVariadicPrintf(char const* format, ...)
{
va_list args;
va_start(args, format);
MyPrintf(format, args);
va_end(args);
}
int main(int, char*)
{
MyVariadicPrintf("%s" /* missing 2nd argument */);
return 0;
}
Я компилирую его с помощью GCC 4.0, используя Xcode в Mac OS X Leopard.
-Wformat и -Wmissing-format-attribute.
Этот код дает предупреждение в строке 9 (вызов vprintf
), предполагая, что MyPrintf
может использовать атрибут 'format':
может быть возможным кандидат для атрибута формата 'printf'
Итак, я добавляю атрибут таким образом (не уверен, что это правильно):
void MyPrintf(char const* format, va_list args) __attribute__((format(printf, 1, 0)));
Предыдущее предупреждение исчезает, и в строке 16 появляется следующее предупреждение (вызов MyPrintf
), предполагая, что MyVariadicPrintf
может использовать атрибут 'format'.
Таким образом, я добавляю атрибут таким образом (на этот раз я уверен, что это правильно):
void MyVariadicPrintf(char const* format, ...) __attribute__((format(printf, 1, 2)));
И теперь я получаю ожидаемое предупреждение в строке 22 (вызов MyVariadicPrintf
):
слишком мало аргументов для формата
- Я сделал это правильно?
- Я заметил, что в объявлении
MyPrintf
, если я удалю часть атрибута, я все равно получу нужное предупреждение в строке 22. Я также заметил, что в этой части атрибута изменение индекса от 1 до 2 не будет дать какое-либо предупреждение или ошибку. Какой из них правильный и какова цель атрибута этой функции?
-
Если добавить следующую функцию MyVariadicPrintfT
и вызвать ее (специализированная с char
), я получу предупреждение, предлагающее использовать атрибут 'format' для этой функции. Я думаю, это невозможно, потому что аргумент format
зависит от шаблонного типа. Я прав?
template<typename Type>
void MyVariadicPrintfT(Type const* format, ...)
{
va_list args;
va_start(args, format);
MyPrintf(format, args);
va_end(args);
}
Последнюю документацию gnu можно найти на gnu.org.
Параметры предупреждения находятся в разделе раздел 3.8 (найдите "-Wimissing-format-attribute-attribute" ).
Атрибуты функции находятся в разделе раздел 6.30 (найдите "формат (архетип, строковый индекс, первый для проверки)" ).
Спасибо.
Ответы
Ответ 1
В документации есть ответ, который вам нужен. В частности:
- Да
- Тот, который вы опубликовали, является правильным (
format(printf, 1, 0)
). 1, потому что строка формата - это параметр 1, 0, потому что нет переменных, которые нужно проверить.
Ответ 2
Взгляните на документы GCC на gnu.org. Что касается последнего вопроса, я предполагаю, что MyPrintf
не является функцией шаблона, и единственное доступное определение принимает в качестве первого аргумента char const*
, поэтому он чувствует себя в безопасности, делая предложение.