我在一本书中读到了这个问题及其答案。但我不明白这本书的理由。
下面的代码会编译吗?
int main()
{
char str[5] = "fast enough";
return 0;
}
答案是:
是的。编译器永远不会检测到 如果数组的边界是错误 超出。
我无法得到它。
有人可以解释一下吗?
答案 0 :(得分:5)
你的书必须很旧,因为即使没有-Wall
开启,gcc也会发出警告:
$ gcc c.c c.c: In function `main': c.c:6: warning: initializer-string for array of chars is too long
如果我们稍微更新程序:
#include <stdio.h>
int main(int argc, char **argv)
{
char str[5] = "1234567890";
printf("%s\n", str);
return 0;
}
我们可以看到gcc似乎将字符串截断为你指定的长度;我假设 发生是'\0'
str[6]
,因为否则我们应该看到5之后的垃圾;但也许gcc隐含地使str
成为长度为6的数组并自动将'\0'
放在那里 - 我不确定。
$ gcc c.c && ./a.exe c.c: In function `main': c.c:6: warning: initializer-string for array of chars is too long 12345
答案 1 :(得分:5)
在C ++标准中,8.5.2 / 2字符数组表示:
没有比数组元素更多的初始化器。
在C99标准中,6.7.8 / 2初始化说:
初始化程序不应尝试为未包含在实体中的对象提供值 被初始化
C90 6.5.7初始化者说类似。
但请注意,对于C(C90和C99),如果有空间,'\ 0'终止字符将被放入数组中。如果终结符不适合,则不是错误(C99 6.7.8 / 14:“字符串文字的连续字符(如果有空间或数组大小未知,则包括终止空字符)初始化元素阵列“)。
另一方面,C ++标准有一个例子,表明如果终止字符没有空间,应该诊断错误。
在任何一种情况下,都应该在所有编译器中诊断为错误:
char str[5] = "fast enough";
也许前ANSI编译器不是那么严格,但任何合理的现代编译器都应该诊断出来。
答案 2 :(得分:2)
您引用的问题的答案不正确。正确的答案是“不。代码将无法编译”,假设一个正式正确的C编译器(而不是某些特定编译器的怪癖)。
C语言不允许使用过长的字符串文字来初始化特定大小的字符数组。这里语言允许的唯一灵活性是终止\0
字符。如果数组太短而无法容纳终止\0
,则会以静默方式删除终止\0
。但是不能删除实际的文字字符串字符。如果文字太长,则违反约束条件,编译器必须发出诊断消息。
char s1[5] = "abc"; /* OK */
char s2[5] = "abcd"; /* OK */
char s3[5] = "abcde"; /* OK, zero at the end is dropped (ERROR in C++) */
char s4[5] = "abcdef"; /* ERROR, initializer is too long (ERROR in C++ as well) */
谁写了你的“书”确实知道他们在谈论什么(至少在这个特定的主题上)。他们在答案中陈述的内容是不正确的。
注意:在C89 / 90,C99和C ++中提供过长的字符串初始值设定项是非法的。然而,在这方面,C ++甚至更具限制性。 C ++禁止丢弃终止\0
字符,而C允许丢弃它,如上所述。
答案 3 :(得分:0)
数组绑定检查在运行时发生,而不是编译时。编译器无法对上述代码进行静态分析,以防止出现错误。
更新:显然上述陈述适用于某些编译器而非其他编译器。如果你的书说它会编译,那么它必须指的是不进行检查的编译器。
答案 4 :(得分:0)
因为“足够快”只是一个指向空终止字符串的指针。编译器要弄清楚是否对char *或char []的赋值超出了数组的范围,这是太多的工作。
答案 5 :(得分:0)
正在发生的事情是你正在尝试初始化一个字符数组,其中的字符数多于数组所具有的空间。以下是它如何分解:
char str[5];
声明一个包含五个字符的字符数组。
char str[5] = "fast enough";
第二部分'=“足够快”;'然后尝试使用“足够快”的值初始化该数组。这不起作用,因为“足够快”比数组长。
然而,它会编译。 C和C ++编译器通常不能为您执行数组边界检查,并且超出数组是分段错误的最常见原因之一。 [编辑]正如Mark Rushakoff指出的那样,显然有些情况下新的确实会发出警告。[/ edit]当你试图运行它时,这可能是段错误的,我更可能认为数组只是被初始化为“快”。