可能重复:
warning: format not a string literal and no format arguments
我有一个非常简单的问题:为什么当我char[] s = "hi"; printf(s)
发出警告时:“警告:格式化不是字符串文字而没有格式参数”,而printf("aa")
则没有。
我已经读过char数组和字符串文字之间的区别(一个是const char const*
,另一个是char*
),但是来自printf()
签名:
我发现它适用于任何类型。所以我的问题是为什么printf("aaa")
不发出任何警告(它是否以某种方式检查文字是一个const,同时数组不是)?
答案 0 :(得分:6)
现在,GNU编译器和许多其他编译器确实根据提供的参数检查printf
- 系列的格式字符串。编译器警告它不能对非文字字符串执行此操作。
使用非文字格式字符串被认为是一种不好的做法。使用您无法控制的格式字符串会更糟糕。
答案 1 :(得分:4)
其原因在于,大约10 - 15年前出现了一系列安全问题,这是由于人们认为在“s”用户提供输入的情况下调用printf是安全的。为避免这些问题,许多编译器为此添加了警告。如果您只想打印出一个字符串,请改用puts()。如果你不完全确定你发送到printf的字符串不包含'%'字符,你应该使用printf(“%s”,s);
答案 2 :(得分:1)
我敢打赌,在第二种情况下,编译器发现字符串中没有格式,因此不危险:
/* "aa" is not dangerous, so do not display a warning */
printf("aa")
在第一种情况下,编译器可能无法看到格式字符串的值,因此无法验证它:
/* the compiler doesn't know the content of the memory region pointed by `s`, so
he can't determine if it's dangerous or not. Then display a warning */
printf(s)
答案 3 :(得分:1)
免责声明:我不知道这是 警告的原因,但它是 的原因。
由于prinrf
的参数数量取决于转换说明符的数量,因此使用字符串文字作为格式字符串(即可能是错误)非常罕见 。此外,如果格式字符串不是文字字符串,它确实来自其他地方 - 例如用户或文件输入。在这种情况下,错误(或恶意)输入可能会导致程序崩溃,或者更糟糕的是,注入代码(即安全漏洞)。
在任何情况下,如果您想要打印不是文字的内容,并且没有格式参数,那么您最有可能寻找puts
,而不是printf
。 (恕我直言,puts
是C库中未被充分利用的功能。你有没有曾经看到“你好,世界”使用它吗?)