2009-06-15 2 views
13

Вот небольшой фрагмент кода:Как использовать атрибут 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):

слишком мало аргументы для формата

  1. Я сделал это правильно?
  2. Я заметил, что в объявлении MyPrintf, если я удалю часть атрибута, я все равно получу нужное предупреждение в строке 22. Я также заметил, что в этой части атрибута изменение индекса от 1 до 2 не даст никакого предупреждения или ошибки. Какой из них правильный и какова цель атрибута этой функции?
  3. Если я добавлю следующую функцию 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 (искать «формат (архетип, строковый указатель, первый для проверки)»).

Спасибо.

ответ

10

В документации есть ответ, который вам нужен.В частности:

  1. Да
  2. Тот, который вы выложили правильно (format(printf, 1, 0)). 1, потому что строка формата является параметром 1, 0, потому что нет переменных аргументов, которые нужно проверить.
+1

В MyVariadicPrintf я понимаю, что компилятор проверяет количество и типы аргументов, начинающихся с позиции 2, на строку в позиции 1. Но в случае с MyPrintf, что проверяет компилятор? – Guillaume

+1

В случае MyPrintf он будет проверять только на правильность строки формата (например, что это не что-то вроде «% _%») – jpalecek

+0

Хорошо, спасибо большое! – Guillaume

3

Посмотрите на GCC docs on gnu.org. Что касается последнего вопроса, то я предполагаю, что MyPrintf не является функцией шаблона и единственным доступным решением является char const* как первый аргумент, поэтому он чувствует себя в безопасности, делая предложение.

Смежные вопросы