代码如下:
FILE *sfp;
....
void test(char *s, ...)
{
va_list ap;
va_start(ap, s);
vfprintf(sfp, s, ap);
fflush(sfp);
va_end(ap);
}
下面报告了编译错误:
error: format string is not a string literal [-Werror,-Wformat-nonliteral]
vfprintf(sfp, s, ap);
如何解决此错误?
答案 0 :(得分:2)
变量永远不是字符串文字。字符串文字是由双引号(即"foo"
)包围的字符序列。
该警告的目的是警告您编译器无法确认分配给vfptrintf
的参数类型与格式字符串匹配。要消除该警告,您将需要
vfprintf
(即vfprintf(sfp, "%d\n", ap)
)format
属性添加到函数声明中(感谢注释中的@chris):即
__attribute__((format(printf, 2, 3)))
void test(FILE* sfp, const char *s, ...)
{
//...
}
或使用标准化的C ++ 11属性语法:
[[gnu::format(printf, 2, 3)]]
void test(FILE* sfp, const char *s, ...)
{
//...
}
请注意,最后一个选项不是标准的C ++属性,因此不适用于所有编译器。例如,您可能还需要其他一些来安抚MSVC。按照标准,如果您使用C ++ 11语法,则编译器应忽略未知属性,但它们仍可能会发出警告,使您回到现在的状况。
如果使用另一个本身不是字符串文字的第二个参数调用test
,您仍然会发出警告。
作为旁注,clang似乎无法检查va_list
printf
函数的参数类型,因此-Wformat-nonliteral在这种情况下实际上没有帮助。 GCC不会发出此警告,可能正是由于该原因。