【问题标题】:__printflike__ modifier__printflike__ 修饰符
【发布时间】:2011-08-15 01:54:45
【问题描述】:

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

【问题讨论】:

  • 你在什么背景下看到它? (你使用的是什么编译器?)
  • gcc 版本 4.2.1 在 unix 上。我对这个术语一无所知,想了解它的基本含义。
  • GCC 不使用 __printflike__ 标识符。它使用语法__attribute__((format(printf, n, m))),并且至少从版本 3.3 开始。如果它存在于您的代码中,您应该发布您在其中看到的代码片段,以便我们为您提供更多帮助。

标签: c printf modifier


【解决方案1】:

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

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

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

其中1, 2 表示format, ... 出现在位置1 和2。

【讨论】:

    【解决方案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__ */
    

    【讨论】:

      【解决方案3】:

      可能告诉编译器对应的函数有printf-like语义。

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

      当调用printfsprintffprintf 等时,编译器无法知道%u 不是int 的正确格式。

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

      【讨论】:

        猜你喜欢
        • 2021-11-06
        • 1970-01-01
        • 2022-06-16
        • 2018-03-04
        • 2015-05-12
        • 2014-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多