Как использовать атрибут GCC 'format'? - PullRequest
13 голосов
/ 15 июня 2009

Вот небольшой кусочек кода:

#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):

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

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

Спасибо.

Ответы [ 2 ]

10 голосов
/ 15 июня 2009

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...