модификатор __printflike__ - PullRequest
       8

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

5 голосов
/ 29 апреля 2011

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

Ответы [ 3 ]

8 голосов
/ 29 апреля 2011

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

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

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

Где 1, 2 означает, что format, ... появляется в позициях 1 и 2.

4 голосов
/ 29 апреля 2011

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

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__ */
1 голос
/ 29 апреля 2011

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

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

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

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

...