Как добраться, printf разрабатывают предупреждения времени компиляции или ошибки

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

Например, если я имею:

{
   int i;
   std::string s;
   printf("%d %d",i);
   printf("%d",s.c_str());
}

Компилятор жалуется как так:

1 cc1plus: warnings being treated as errors
2 In function 'int main()':
3 Line 8: warning: too few arguments for format
4 Line 9: warning: format '%d' expects type 'int', but argument 2 has type 'const char*'

пример кода

printf и co специальные функции то, что компилятор рассматривает по-другому или является там некоторым приемом к тому, чтобы заставлять это работать над какой-либо определяемой пользователем функцией? Определенные компиляторы, которыми я интересуюсь, являются gcc и msvc

12
задан Hippicoder 23 June 2010 в 20:07
поделиться

5 ответов

Разные компиляторы могут реализовывать эту функциональность по-разному. В GCC это реализовано через спецификатор __attribute__ с атрибутом format (читайте об этом здесь). Причина, по которой компилятор выполняет проверку, заключается в том, что в стандартных заголовочных файлах, поставляемых с GCC, функция printf объявлена с __attribute__((format(printf, 1, 2)))

Точно так же вы можете использовать атрибут format для расширения той же функциональности проверки формата на ваши собственные вариативные функции, которые используют те же спецификаторы формата, что и printf.

Все это будет работать только в том случае, если соглашение о передаче параметров и используемые вами спецификаторы формата совпадают с теми, которые используются стандартными функциями printf и scanf. Проверки жестко закодированы в компиляторе. Если вы используете другое соглашение для передачи переменных аргументов, компилятор не поможет вам проверить это.

19
ответ дан 2 December 2019 в 05:26
поделиться

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

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

Если вы используете C ++, я бы не стал писать свои собственные вариативные функции; есть несколько веских причин использовать их в большинстве проектов. Например, если вы выполняете форматирование, используйте потоки или библиотеку, например Boost Format . Любую проблему, которую можно решить с помощью функции с вариациями, можно решить с помощью функции без вариации, и почти во всех случаях результат будет более элегантным, идиоматическим и безопасным для типов.

2
ответ дан 2 December 2019 в 05:26
поделиться

Некоторое время назад кто-то отправил mpl :: string в группы повышения. Думаю, он действительно попал в библиотеку. Если это так, вы можете реализовать что-то подобное, указав строку шаблона в качестве параметра шаблона (mpl :: string), а затем используя некоторые довольно глубокие навыки метапрограммирования для анализа битов форматирования в нем. Затем вы могли бы использовать эту информацию, чтобы выбрать реализацию, которая имеет соответствующее количество аргументов и типы.

Нет, я не собираюсь делать это за вас: P Это будет довольно сложно. Однако я верю, что это было бы возможно.

1
ответ дан 2 December 2019 в 05:26
поделиться

Это поведение сильно зависит от компилятора. Я считаю, что gcc предоставляет интерфейс для проверки типов переменных функций.

5
ответ дан 2 December 2019 в 05:26
поделиться

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

Вместо того, чтобы пытаться заставить компилятор помочь вам таким образом, попробуйте использовать подход, используемый стандартными потоками: используйте функцию или оператор (возможно, шаблон), который возвращает ссылку на this для разрешить цепочку. Тогда компилятор сможет сразу сказать вам, когда аргументы не соответствуют ожидаемым / поддерживаемым.

1
ответ дан 2 December 2019 в 05:26
поделиться
Другие вопросы по тегам:

Похожие вопросы: