2010-09-14 2 views
4

Я заметил, что большое количество компиляторов C выдает предупреждения, когда спецификаторы преобразования в строке формата функций printf/sprintf не соответствуют типу или счету соответствующих аргументов.Предупреждения о компиляторе printf/sprintf - концептуальный разрыв?

Это кажется мне концептуальным перерывом, поскольку C не имеет встроенных функций в соответствии со спецификацией языка.

Весь компилятор должен знать о printf/sprintf, это их прототипы, а не их семантика. Я знаю, что printf/sprintf являются стандартными функциями C, но все же они находятся в отдельной библиотеке libc, и вы должны включить stdio.h для импорта своих прототипов.

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

Означает ли это вышеизложенное?

+0

Концептуальный разрыв от чего? –

+0

Одно слово: QOI (ну: 3 на самом деле) – pmg

+0

@Martin: Насколько я знаю, C не имеет встроенных функций. Как тогда компилятор понимает семантику функций printf/sprintf, когда они определены во внешней библиотеке? –

ответ

11

«Все компилятор должен знать о Printf/Sprintf является их прототипами, а не их семантика».

Это часть, которая не соответствует действительности. Что касается стандарта, любая часть реализации C «разрешается» знать о какой-либо другой части и выдавать диагностику, которая может быть полезной для пользователя. Стандарт компилятора не требуется стандартом, и ни одна из них не является диагностикой, но они, конечно же, не запрещены.

Обратите внимание, что стандартная библиотека является специальной, это не только старая связанная библиотека. Если конкретная реализация/компилятор даже предоставляет механизм для соединения пользователя с другой версией стандартной библиотеки, стандарт, конечно же, не требует, чтобы он «работал», когда эта альтернативная библиотека имеет разную семантику из того, что изложено в стандарт.

Итак, в этом смысле все в стандартной библиотеке является «bult-ins». Это часть спецификации языка C. Составителям разрешено действовать исходя из предположения, что он ведет себя по мере необходимости.

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

1

Эти предупреждения указывают на вероятные ошибки и, как результат, полезны.

Да, это может выглядеть нелогично иметь особые случаи для предупреждений в компиляторе (предполагается, что <stdio.h> не только имеют атрибут __printf_format_warning или что-то подобное), но опять же, если это полезно и помогает решить некоторые ошибки (возможно, даже ошибки безопасности), то почему бы не иметь их?

Я имею в виду, это не так, как все просто заменяют их Libc с их собственным, с различной PRINTF семантикой ...

2

Если я правильно прочитал ваш вопрос, я согласен с вашей предпосылкой, что проверка printf и строки формата друзей компилятором является концепцией, отличной от других видов статической проверки (синтаксиса, типа и т. Д.), Выполняемых компилятор.

Тем не менее, это разрешено стандартом, и это помогает нам бедные программисты.

2

Задача компилятора состоит в том, чтобы дать вам несколько полезных советов.Это не распространяется на стандарт.

Реализация может генерировать предупреждения во многих ситуациях, ни одна из которых не является , указанной в рамках настоящего международного стандарта.

Теоретически, ничто не мешает компилятору предупреждать вас о (потенциально) неправильном использовании, скажем, библиотеки QT.

И printf является стандартной функцией в том смысле, что она (включая ее семантику) покрыта стандартом ISO C.

2

Стандарт требует диагностики при некоторых обстоятельствах, но не запрещает общую диагностику. Любая реализация может бесплатно выпустить диагностику по любой причине, включая неправильное использование printf() или чрезмерное использование буквы Q. Очевидно, что некоторые из этих причин более полезны, чем другие.

Кроме того, если вы включаете библиотеку, все видимые идентификаторы в ней становятся зарезервированными. Вам не разрешено #include <stdio.h> и имеют собственное определение printf (см. 7.1.3 проекта стандарта C99). Это означает, что в реализации можно предположить, что вы используете стандарт printf и относитесь к нему так, как если бы это была обязательная часть стандарта.

+0

«Стандарт требует диагностики при некоторых обстоятельствах» - нет, это не так, см. Цитату в моем ответе (это из ISO/IEC 9899: TC2). Или вы можете указать мне место (возможно, в некоторых других стандартах ISO или ANSI C?), Где это происходит? –

+1

У меня есть проект стандарта C99 здесь (не принадлежит реальная копия), и в 5.1.1.3 я нахожу, что «Соответствующая реализация должна содержать по меньшей мере одно диагностическое сообщение (идентифицированное определенным образом), если блок перевода для предварительной обработки или блок перевода содержит нарушение любого синтаксического правила или ограничения, даже если поведение также явно указано как неопределенное или определенное реализацией ». Это пропущено из окончательной версии? –

+0

@ Roman: Также мне кажется, что это с самого начала приложения I (информативное) под названием «Общие предупреждения». Это относится к предупреждающим сообщениям, а не к диагностическим сообщениям (в стандартах, точная формулировка может быть важна) и, по-видимому, в любом случае не является нормативной. –

1

Конечная цель программирования языковых стандартов - помочь программистам писать программы, которые ведут себя по назначению. В стандарте нет ничего, что говорит о том, что компилятор должен выдать предупреждение, если он встречает «bigvar = byte3» < < 24 + byte2 < < 16 + byte1 < + byte0; ", но поскольку результаты, вероятно, не являются тем, что программист многие компиляторы выдают предупреждение. Единственное ограничение, устанавливаемое стандартами на предупреждения, заключается в том, что они не должны препятствовать успешной компиляции законной программы (например, компилятор, который не смог выполнить ошибку после вывода предупреждений 999 или выдал столько предупреждений, что компиляция для всех практических целей, никогда не завершится, будет несоответствие).

Существует не требование, чтобы компилятор «знал» о стандартных библиотеках, но не существует каких-либо требований, чтобы он не знал о них, если кто-то # включает обычные заголовки. Действительно, , если программа включает в себя <stdio.h> Я думаю, было бы допустимо под стандартом для компилятора заменить вызов printf, который он может понять, с чем-то, что может быть легче обработать во время выполнения (например, он может замените printf («Q% 5d», foo), с «putch ('Q'); __put_int (foo, 5);" при желании). Если в программе нет #include <stdio.h> такой перевод будет запрещен.

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