很抱歉,如果这是一个菜鸟问题:(。
一段C代码。
int array[5];
int cnt;
for(cnt = 0; cnt <= 10; cnt+=1)
{
array[cnt] = cnt;
}
应该给出错误,对吗?没有!工作良好! 但那是为什么呢?似乎 - 在第一行 - 定义了超过双倍大小(11)的数组。您甚至可以稍后访问数组[5到10]。这让我很困惑。当您定义数组[4或更少] ...
时,它将停止工作提前致谢。
答案 0 :(得分:23)
它可能适用于您的特定编译器和计算机,但您不应指望它。
根据C语言规范,您的代码行为是 undefined 。这意味着它可能会执行您希望的操作,或者可能导致计算机崩溃,或者可能导致demons to fly out your nose。
与Java和C#等高级语言不同,C信任您,并且不会对数组的边界执行显式检查。你应该负责,而不是超越阵列的界限。
答案 1 :(得分:16)
如果您对“作品”的定义与“尚未崩溃”同义,则此仅“有效”。
答案 2 :(得分:5)
您看到的是未定义的行为,这是由您使用无效索引访问数组引起的。未定义的行为意味着任何事情都可能发生,包括您的程序似乎正常工作。
答案 3 :(得分:4)
“但为什么会这样?”
因为这就是C的方式。
运行时不检查数组边界。
这就是“C的法则”
答案 4 :(得分:4)
我只想指出所有这些确实是未定义的。 您的示例在此特定示例中“起作用”,因为两个变量都位于堆栈中。那就是cnt的地址就在数组的末尾。当cnt达到cnt == 5时 语句数组[cnt] = cnt;不写在专用于数组的内存中,而是写在cnt的地址之后。只是运气,它不会改变你的柜台。 当cnt> 5时,没有内存可以删除,它只会写入“stack void”(不知道正确的单词)。
另一个例子来说明这一点:
int main(int ac,char **av)
{
int a[5];
int cnt;
int cnt2=3;
for(cnt=0;cnt<7;cnt++) {
a[cnt]=cnt;
printf("%d %d %d\n", a[cnt], cnt, cnt2);
}
}
输出:
0 0 3
1 1 3
2 2 3
3 3 3
4 4 3
5 5 5
6 6 5
循环的最后两次写入会在[]之后覆盖堆栈数据,并且可能会产生非常混乱的错误。在这种情况下,cnt2被删除了。
答案 5 :(得分:2)
在运行时不检查C中的数组。换句话说,您可以“定义”一个大小为N的数组,并愉快地访问数组绑定的末尾。如果你离开数组的末尾,那么你将在堆栈(或堆)的某处丢弃内存。
一旦你将内存丢弃,你的程序可能会崩溃。这些崩溃可能很难追踪,因为它们可能会远离您实际覆盖阵列末端的位置。
通常,当您在C中声明数组时,最好使用某种常量或#define来标记数组的大小:
#define MAX_ELEMENTS 10
int array[MAX_ELEMENTS];
int cnt;
for(cnt = 0; cnt < MAX_ELEMENTS; cnt+=1) {
array[cnt] = cnt;
}
如果在数组赋值中超过MAX_ELEMENTS,则可能会覆盖cnt的值。您可能会覆盖其他一些变量。一切都取决于编译器和代码结构。还要注意使用&lt;登录for循环。 C数组基于0,因此您必须使用小于或小于或等于来检查。
答案 6 :(得分:1)
C中的数组边界在运行时不一定检查。如果选择或不选择标准,实现者可以自由地执行此操作 - 这是 undefined 的一部分。在使用胖指针的实现上,示例可能确实会导致某种错误。
答案 7 :(得分:0)
一旦你运行了数组的末尾,你就会覆盖软件不期望的内存并破坏堆。你的软件可能会继续运行,但它会非常不稳定!
答案 8 :(得分:0)
取决于堆栈内存的打包方式。此外,它会愉快地覆盖这些值甚至读取它们,但很可能你正在破坏堆栈。