数组中的元素太多了!

对不起,如果这是一个菜鸟问题:(。

一块C代码。

int array[5]; int cnt; for(cnt = 0; cnt <= 10; cnt+=1) { array[cnt] = cnt; } 

应该给出错误吧? 没有! 工作良好! 但那是为什么呢? 似乎 – 在第一行 – 定义了超过双倍大小(11)的数组。 您甚至可以稍后访问数组[5到10]。 这让我很困惑。 定义数组[4或更少]时它停止工作…

提前致谢。

它可能恰好适用于您的特定编译器和计算机,但您不应指望它。

根据C语言规范的代码行为未定义 。 这意味着它可能会按照您的意愿行事,或者可能导致计算机崩溃,或者可能导致恶魔飞出您的鼻子 。

与Java和C#等高级语言不同,C信任您并且不对数组的边界执行显式检查。 你应该负责,而不是超越arrays的边界。

如果您对“作品”的定义与“尚未崩溃”同义,那么这只会“有效”。

您所看到的是由于您使用无效索引访问数组而导致的未定义行为 。 未定义的行为意味着任何事情都可能发生,包括您的程序似乎正常工作。

“但那为什么呢?”

因为这就是C的方式。

在运行时不检查数组边界。

这就是“C的法则”

我只想指出所有这些确实是未定义的。 您的示例在此特定示例中“起作用”,因为两个变量都位于堆栈中。 那就是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被删除。

不在运行时检查C中的数组。 换句话说,您可以“定义”一个大小为N的数组,并愉快地访问数组绑定的末尾。 如果你离开数组的末尾,那么你将在堆栈(或堆)的某处丢弃内存。

一旦你在某个地方丢弃了内存,你的程序很可能会崩溃。 这些崩溃可能很难追踪,因为它们可能会远离您实际覆盖arrays末端的位置。

通常,当您在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的值。 您可能会覆盖其他一些变量。 一切都取决于编译器和代码结构。 另请注意在for循环中使用

C中的数组边界不一定在运行时检查。 标准使得实现者可以自由选择,如果他们选择或不选择 – 这是未定义的部分。 在使用胖指针的实现上,示例可能确实会导致某种错误。

一旦你运行了数组的末尾,你将覆盖软件不期望的内存并破坏堆。 你的软件可能继续运行,但它会非常不稳定!

取决于堆栈内存的打包方式。 此外,它会愉快地覆盖这些值甚至读取它们,但很可能你正在破坏堆栈。