Как использовать формат атрибута GCC?

Вот небольшой фрагмент кода:

#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 зависит от шаблонного типа. Я прав?

    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 (ищите "-Wmissing-format-attribute").< br> Атрибуты функций находятся в разделе 6.30 (ищите «формат (архетип, индекс строки, первый для проверки)»).

Спасибо.


person Guillaume    schedule 15.06.2009    source источник


Ответы (2)


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

  1. да
  2. Тот, который вы разместили, правильный (format(printf, 1, 0)). 1, потому что строка формата является параметром 1, 0, потому что нет проверяемых аргументов с переменным числом аргументов.
person jpalecek    schedule 15.06.2009
comment
Я понимаю, что в MyVariadicPrintf компилятор будет проверять количество и типы аргументов, начинающихся в позиции 2, по строке в позиции 1. Но что компилятор проверяет в случае с MyPrintf? - person Guillaume; 16.06.2009
comment
В случае MyPrintf он будет проверять только правильность строки формата (например, что это не что-то вроде %_%) - person jpalecek; 16.06.2009

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

person D.Shawley    schedule 15.06.2009