__printflike__修饰符

时间:2011-04-28 21:29:58

标签: c printf modifier

究竟是什么是“__printflike__修饰符”?这个术语是什么意思?

3 个答案:

答案 0 :(得分:8)

猜测它告诉编译器你正在使用一个函数接受[anything, ] format, ...形式的参数,其中format, ...部分看起来像printf的参数。 __printflike__属性允许编译器根据字符串格式测试参数列表中的类型。当您编写像log(format, ...)这样的函数并使用vsprintf将格式化工作从属于通常的标准库函数,然后将字符串发送到某个特殊的日志界面时,就会出现这种情况。

如果您正在使用GCC,那么项目中的#define可能类似于:

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

1, 2表示format, ...出现在第1和第2位。

答案 1 :(得分:4)

我的错误报告库中有一个函数,标题中的声明如下:

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));

我将收到编译错误,因为errnointstrerror(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__ */

答案 2 :(得分:1)

可能告诉编译器相应的函数有printf - 就像语义一样。

这可以使编译器在编译时发出警告,当格式字符串中的修饰符与传递的参数的类型或计数不对应时。

在调用%uint时,编译器没有其他方式可以告诉您printf不是sprintf的正确格式,fprintf等。

几个月前我问过相反的问题:Are printf/sprintf compiler warnings a conceptual break?