为什么在Clang中使用__attribute__((__format__(__printf_..))来避免格式化字符串

Why use __attribute__((__format__ (__printf__,...) in Clang to avoid format string is not a string literal?

本文关键字:字符串 格式化 printf format 为什么 attribute Clang      更新时间:2023-10-16

这里和这里都建议,为了避免Clang中出现"格式字符串不是字符串文字"的警告,应该在函数定义之前使用以下__attribute__代码段来告诉Clang printf家族的一个函数正在函数内部调用:

__attribute__((__format__ (__printf__, 3, 0)))

我的问题是为什么?我看过这里的官方文件,但不能真正指出这个问题。

重点是,将任意输入作为printf格式字符串传递通常是一个非常糟糕的想法。一个类型不匹配,您就得到了一张通往Undefined Behavior的单程票(更不用说可怕的%n说明符,它可能会导致写入不匹配的任意内存)。

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