Модификатор __printflike__

Что такое "модификатор __printflike__"? Что означает этот термин?

3 ответа

Решение

В предположении он сообщает компилятору, что вы используете, что функция принимает аргументы в форме [anything, ] format, ... где format, ... часть выглядит как аргументы printf, __printflike__ Атрибут позволяет компилятору проверять типы в списке аргументов на соответствие строковому формату. Это появляется, когда вы пишете такую ​​функцию, как log(format, ...) и использовать vsprintf подчинить работу форматирования обычным функциям стандартной библиотеки перед отправкой строки в какой-то специальный интерфейс журнала.

Если вы используете GCC, то это, вероятно, #define в вашем проекте что-то вроде:

#define __printflike__ __attribute__((format(printf, 1, 2)))

куда 1, 2 Значит это format, ... появляются в позициях 1 и 2.

У меня есть функция в моей библиотеке отчетов об ошибках с объявлением в заголовке, например:

extern void err_logmsg(FILE *fp, int flags, int estat, const char *format, ...)
                       PRINTFLIKE(4,5);

PRINTFLIKE в верхнем регистре, так что я могу определить его как ничего, когда я не использую GCC. Это использование говорит о том, что первые три аргумента не являются чем-то особенным, но четвертый аргумент является строкой формата, подобной тем, которые используются printf() (действительно, внутренне, это передается vfprintf()) и соответствующие ей аргументы (отформатированные с использованием строки формата) начинаются с пятого аргумента.

Это означает, что если я наберу:

err_logmsg(stdout, ERR_ABORT, 1, "%s: %d\n", errno, strerror(errno));

Я получу ошибку компиляции, потому что errno является int а также strerror(errno) возвращает указатель на строку. Я могу исправить ошибку, изменив формат строки или пятый и шестой аргументы. (ERR_ABORT - это набор флагов, определенных в том же заголовке, который объявляет err_logmsg().)

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

extern void err_writer(FILE *fp, const char *format, int flags, int estat, ...)
                       PRINTFLIKE(2,5);

Это говорит компилятору, что строка формата является вторым аргументом, но соответствующие аргументы, которые форматируются, все еще появляются, начиная с пятого аргумента.

Заголовочный файл для этого кода содержит строки:

#ifdef __GNUC__
#define PRINTFLIKE(n,m) __attribute__((format(printf,n,m)))
#define NORETURN()      __attribute__((noreturn))
#else
#define PRINTFLIKE(n,m) /* If only */
#define NORETURN()      /* If only */
#endif /* __GNUC__ */

Вероятно, сообщает компилятору, что соответствующая функция имеет printfсемантика

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

Нет другого способа, которым компилятор мог бы сказать, что %u не правильное форматирование для int при звонке printf, sprintf, fprintf, так далее.

Несколько месяцев назад я задал обратный вопрос: являются ли предупреждения компилятора printf/sprintf концептуальным разрывом?

Другие вопросы по тегам