Подтвердить что ты не робот

Как использовать атрибут 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 (найдите "формат (архетип, строковый индекс, первый для проверки)" ).

Спасибо.

4b9b3361

Ответ 1

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

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

Ответ 2

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