2013-12-06 2 views
5

я написал это намеренно неправильного код-Werror = формат: как компилятор знает

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

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

Компилятор дает это очень внушительное предупреждение:

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

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

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

+0

«потому что строка формата не анализируется до времени исполнения», вы уверены? Это интересно, если это правда. Не имеет смысла, чтобы меня оставили на время исполнения. –

+5

Компилятор не анализирует магический код. Он имеет специальную проверку для 'printf' и аналогичных функций' libc'. Он не будет автоматически работать с вашими собственными функциями. – Jesper

ответ

9

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

Пока строка формата является строковым литералом, ее можно разобрать во время компиляции. Если это не так (обычно это плохая идея), тогда вы можете получить предупреждение об этом от -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.

+0

этот '__attibute__' очень полезен. У Clang и MSVC++ есть что-то похожее? – XPlatformer

+1

@ user3001464: Clang имеет тот же атрибут, что и GCC. Я никогда не использую компилятор Microsoft, но [этот вопрос] (http://stackoverflow.com/questions/2354784), похоже, указывает, что есть что-то подобное. –

5

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

Документация -Wformat говорит, что это именно то, что происходит:

-Wformat

-Wformat=n

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

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

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

+0

Что касается использования этой функции для ваших собственных функций, вы можете и не можете. Вы можете указать атрибут 'format' для своих собственных функций, но вы должны указать, какую из строк стандартного формата он использует; вы не можете придумать что-то совершенно новое. –

+0

@JamesKanze: Спасибо, я не знал об этом. – Jon

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