Вот небольшой фрагмент кода:Как использовать атрибут 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
может использовать «формат» атрибут:
функция может быть возможным кандидатом для атрибута формата «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.org.
Предупреждающие параметры указаны в section 3.8 (ищите «-Исход-формат-атрибут»).
Атрибуты функции находятся в формате section 6.30 (искать «формат (архетип, строковый указатель, первый для проверки)»).
Спасибо.
В MyVariadicPrintf я понимаю, что компилятор проверяет количество и типы аргументов, начинающихся с позиции 2, на строку в позиции 1. Но в случае с MyPrintf, что проверяет компилятор? – Guillaume
В случае MyPrintf он будет проверять только на правильность строки формата (например, что это не что-то вроде «% _%») – jpalecek
Хорошо, спасибо большое! – Guillaume