我正在尝试为调试打印定义一个类方法,其行为类似于
printf
:
inline void debug(const char* fmt, ...) __attribute__ ((format (printf, 1, 2)))
当我使用
-Wformat
或 -Wall
进行编译时,这会抱怨:
error: format string argument not a string type
我记得类方法声明有一个隐式的
this
参数,所以我将参数的位置更改为 2、3:
inline void debug(const char* fmt, ...) __attribute__ ((format (printf, 2, 3)))
现在它可以编译了,但看起来参数被移动了,就好像
this
参数被视为参数列表的一部分一样。
如何告诉函数
this
不是我要打印的字符串的一部分?
你已经做到了。
this
是参数 1,因此通过说 format(printf, 2, 3)
,您告诉编译器您没有打印 this
,而是打印参数 2 (fmt
) 以及其他参数。
将静态成员与非成员同等对待。讨论给了我答案,但其他人值得注意:
我发现这一点是因为我们有一些进程使用这样的日志助手,并且四分之一的进程需要
__attribute__ (( format( printf, 2, 3 ) ))
,而其他三个与 __attribute__ (( format(printf, 1, 2) ))
配合得很好 - 事实证明它是非静态的......
用途:
inline void debug(const char* fmt, ...) __attribute__ ((format (printf, 2, 3)));
由于
debug()
是 C++ 类成员函数,因此它的第一个参数自动隐式地是类的 this
参数。因此,使用 (printf, 2, 3)
表示 2
是格式字符串 string-index,这意味着第二个参数(即:this
之后的第一个参数)是格式字符串,而 3
是格式字符串。 first-to-check 参数,这意味着第三个参数是与格式字符串对应的第一个值。
这里有最新的 gcc 文档来支持它(感谢 Foxit reader 让我在 Linux 上标记 PDF)。特别注意下图中绿色标记的部分。
由于非静态 C++ 方法具有隐式
参数,因此在为 string-index 和 first-to-check 提供值时,此类方法的参数应从 two 开始计数,而不是从 1 开始。this
来源:https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes(请参阅标题为“格式(原型,字符串索引,首先检查)”)。
图像(尤其是绿色突出显示):
由于它仅适用于 gcc,因此最好以这种方式定义它以避免在其他编译器上出现错误。
#ifdef __GNUC__
__attribute__ (( format( printf, 2, 3 ) ))
#endif