-Werror = format: откуда компилятору узнать

Я написал намеренно неправильный код

printf("%d %d", 1);

компиляция с g++ и -Werror=format.

Компилятор выдает очень впечатляющее предупреждение:

error: format '%d' expects a matching 'int' argument [-Werror=format]

Насколько я понимаю, компилятор не может определить, что код неправильный, потому что строка формата не анализируется до времени выполнения.

Мой вопрос: есть ли у компилятора специальная функция, которая срабатывает для printf и аналогичных функций libc, или это функция, которую я мог бы использовать для своих собственных функций? Строковые литералы?


person XPlatformer    schedule 06.12.2013    source источник
comment
потому что строка формата не анализируется до времени выполнения, вы уверены? Это интересно, если это правда. Для меня не имеет смысла оставаться на время выполнения.   -  person Kiril Kirov    schedule 06.12.2013
comment
Компилятор не выполняет магический анализ кода. Он имеет специальную проверку регистра для printf и аналогичных libc функций. Он не будет автоматически работать с вашими собственными функциями.   -  person Jesper    schedule 06.12.2013


Ответы (2)


Насколько я понимаю, компилятор не может определить, что код неправильный, потому что строка формата не анализируется до времени выполнения.

Пока строка формата является строковым литералом, ее можно проанализировать во время компиляции. Если это не так (что обычно является плохой идеей), вы можете получить предупреждение об этом от -Wformat-security.

есть ли у компилятора специальная функция, которая срабатывает для printf и подобных функций libc?

да.

или это функция, которую я мог бы использовать для своих собственных функций?

Да, если вы используете тот же стиль строки формата, что и printf (или различные другие стандартные функции, такие как scanf или strftime).

void my_printf(Something, char const * format, SomethingElse, ...)
    __attribute__ ((format (printf,2,4)));

чтобы указать, что второй аргумент является строкой формата в стиле printf, а значения для форматирования начинаются с четвертого. См. http://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html. .

person Mike Seymour    schedule 06.12.2013
comment
это __attibute__ очень полезно. Есть ли у Clang и MSVC ++ что-нибудь похожее? - person XPlatformer; 06.12.2013
comment
@ user3001464: Clang имеет тот же атрибут, что и GCC. Я никогда не использую компилятор Microsoft, но этот вопрос, похоже, указывает на то, что есть нечто подобное. - person Mike Seymour; 06.12.2013

Что ж, printf определенно анализирует строку формата во время выполнения, чтобы выполнить свою работу. Но нигде не написано, что компилятор может не анализировать его сам, если захочет.

В документации для -Wformat сказано, что именно это и происходит:

-Wformat

-Wformat=n

Проверьте вызовы printf и scanf и т. Д., Чтобы убедиться, что предоставленные аргументы имеют> типы, соответствующие указанной строке формата, и что преобразования, указанные в строке формата, имеют смысл. Сюда входят стандартные функции и другие, определенные атрибутами формата (см. Атрибуты функций) в семействах printf, scanf, strftime и strfmon (расширение X / Open, не в стандарте C) (или других целевых семействах). Какие функции проверяются без указания атрибутов формата, зависит от выбранной стандартной версии, и такие проверки функций без указанного атрибута отключаются -ffreestanding или -fno-builtin.

Форматы проверяются на соответствие функциям формата, поддерживаемым GNU libc версии 2.2. К ним относятся все функции ISO C90 и C99, а также функции из спецификации Single Unix и некоторые расширения BSD и GNU. Другие реализации библиотеки могут не поддерживать все эти функции; GCC не поддерживает предупреждения о функциях, выходящих за рамки ограничений конкретной библиотеки. Однако, если -Wpedantic используется с -Wformat, выдаются предупреждения о функциях формата, не входящих в выбранную стандартную версию (но не для форматов strfmon, поскольку их нет ни в одной из версий стандарта C). См. Параметры, управляющие диалектом C.

Обновление. Оказывается, вы можете использовать его в своих собственных функциях. У Майка есть подробности.

person Jon    schedule 06.12.2013
comment
Что касается использования этой функциональности для ваших собственных функций: вы можете и не можете. Вы можете указать атрибут format для своих собственных функций, но вы должны указать, какую из строк стандартного формата он использует; вы не можете изобрести что-то совершенно новое. - person James Kanze; 06.12.2013
comment
@JamesKanze: Спасибо, я не знал об этом. - person Jon; 06.12.2013