为什么printf(char [])会生成警告,而printf(“asdf”)则不会

时间:2012-07-10 15:04:55

标签: c gcc printf

  

可能重复:
  warning: format not a string literal and no format arguments

我有一个非常简单的问题:为什么当我char[] s = "hi"; printf(s)发出警告时:“警告:格式化不是字符串文字而没有格式参数”,而printf("aa")则没有。

我已经读过char数组和字符串文字之间的区别(一个是const char const*,另一个是char*),但是来自printf()签名:

http://www.gnu.org/software/libc/manual/html_node/Formatted-Output-Functions.html#Formatted-Output-Functions

我发现它适用于任何类型。所以我的问题是为什么printf("aaa")不发出任何警告(它是否以某种方式检查文字是一个const,同时数组不是)?

4 个答案:

答案 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库中未被充分利用的功能。你有没有曾经看到“你好,世界”使用它吗?)