我应该如何在 C++ 的类方法中正确使用 __attribute__ ((format (printf, x, y))) ?

问题描述 投票:0回答:4

我正在尝试为调试打印定义一个类方法,其行为类似于

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
不是我要打印的字符串的一部分?

c++ gcc printf string-formatting
4个回答
44
投票

你已经做到了。

this
是参数 1,因此通过说
format(printf, 2, 3)
,您告诉编译器您没有打印
this
,而是打印参数 2 (
fmt
) 以及其他参数。


6
投票

将静态成员与非成员同等对待。讨论给了我答案,但其他人值得注意:

  • 非成员函数适用于 1,2
  • 静态成员函数适用于 1,2
  • 非静态成员函数将“this”视为#1,因此需要 2,3

我发现这一点是因为我们有一些进程使用这样的日志助手,并且四分之一的进程需要

__attribute__ (( format( printf, 2, 3 ) ))
,而其他三个与
__attribute__ (( format(printf, 1, 2) ))
配合得很好 - 事实证明它是非静态的......


6
投票

@Chris Dodd 是正确的

用途:

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++ 方法具有隐式

this
参数,因此在为 string-indexfirst-to-check 提供值时,此类方法的参数应从 two 开始计数,而不是从 1 开始。

来源https://gcc.gnu.org/onlinedocs/gcc-8.2.0/gcc/Common-Function-Attributes.html#Common-Function-Attributes(请参阅标题为“格式(原型,字符串索引,首先检查)”)。

图像(尤其是绿色突出显示):


3
投票

由于它仅适用于 gcc,因此最好以这种方式定义它以避免在其他编译器上出现错误。

#ifdef __GNUC__
          __attribute__ (( format( printf, 2, 3 ) ))
#endif
© www.soinside.com 2019 - 2024. All rights reserved.