为什么在 Clang 中使用 __attribute__((__format__ (__printf__,...) 来避免格式​​字符串不是字符串文字?

use*_*318 3 c c++ clang clang-static-analyzer

此处此处建议为避免在 Clang 中出现警告“格式字符串不是字符串文字”,应__attribute__在函数定义之前使用以下代码部分来告诉 Clang,该函数printf内部正在调用 family 中的函数之一:

__attribute__((__format__ (__printf__, 3, 0)))
Run Code Online (Sandbox Code Playgroud)

我的问题是为什么?我在这里查看了官方文档但无法真正指出问题。

T.C*_*.C. 7

关键是将任意输入作为格式字符串传递通常是一个非常糟糕的主意printf。一种类型不匹配,你得到了一张通往未定义行为领域的单程票(更不用说可怕的%n说明符,它会导致写入任意内存的不匹配)。

因此,如果您printf使用非文字调用,GCC 和 clang 会抱怨(如果您使用文字格式字符串调用它,它们将根据提供的参数检查格式字符串)。该__attribute__((__format__ (__printf__,...)告诉编译器,你的参数之一是一个printf格式字符串,并导致当调用该函数将被应用的检查。由于编译器知道在调用您的函数时将检查格式字符串参数,因此它不会抱怨您将该参数用作函数内的格式字符串。