5

可能重复:
警告:格式不是字符串文字,也没有格式参数

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

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

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

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

4

4 回答 4

6

如今,GNU 编译器和许多其他编译器确实printf会根据提供的参数检查 -family 的格式字符串。编译器警告它不能对非文字字符串执行此操作。

使用非文字格式字符串被认为是一种不好的做法。使用您无法控制的格式字符串会更糟。

于 2012-07-10T15:08:40.437 回答
4

原因是大约 10 到 15 年前,人们假设在“s”有用户提供的输入时调用 printf(s) 是安全的,导致了一堆安全问题。许多编译器为此添加了警告以避免这些问题。如果您只想打印出一个字符串,请改用 puts()。如果您不能绝对确定要发送到 printf 的字符串不包含 '%' 字符,则应使用 printf("%s", s);

于 2012-07-10T15:11:11.017 回答
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)
于 2012-07-10T15:07:52.500 回答
1

免责声明:我不知道这是否是警告原因,但这是一个原因。

由于参数的数量prinrf取决于转换说明符的数量,因此使用字符串文字作为格式字符串是非常罕见的(即,可能是错误)。此外,如果格式字符串不是文字,它确实来自其他地方——例如用户或文件输入。在这种情况下,错误(或恶意)输入可能会使您的程序崩溃,或者更糟的是,注入代码(即安全漏洞)。

在任何情况下,如果你想打印一些不是文字的东西,并且没有格式参数,那么你很可能正在寻找puts,而不是printf无论如何。(恕我直言,puts是 C 库中使用最少的一个函数。你见过使用它的“hello, world”吗?)

于 2012-07-10T15:10:59.513 回答