You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数组越界为何返回0?ModifyArray函数的影响分析

为什么调用ModifyArray后,越界访问Array2[6]总是返回0?

先看你的代码:

#include <stdio.h>
void ModifyArray(int *ptr1, int *ptr2, int *ptr3) {
    for(int i = 0; i<4; i++) {
        ptr3[i] = ptr1[i+0] - ptr2[i+3];
    }
}
int main() {
    int Array1[6];
    int Array2[6];
    int Array3[6];
    ModifyArray(&Array1[0], &Array2[0], &Array3[0]);
    printf("%d\n", Array2[6]);
    return 0;
}

首先必须明确:访问Array2[6]本身就是C标准定义的未定义行为——Array2只有6个元素,合法索引范围是0到5,Array2[6]已经超出了数组的内存边界。C语言标准对这种情况没有任何保证,理论上它可以是任意值、导致程序崩溃,甚至触发其他奇怪的行为。你观察到的“稳定返回0”只是特定编译环境下的巧合,不是必然结果。

那为什么调用ModifyArray后会出现这个巧合?我们可以结合常见的栈布局和函数执行逻辑来分析:

  • 栈上局部变量的排列:在大多数编译器(比如GCC)的默认设置下,main函数里的局部变量会按声明顺序从高地址到低地址分配(因为栈是从高地址向低地址增长的)。也就是说,三个数组在栈上的地址顺序是:Array1 → Array2 → Array3,彼此连续。

  • 越界地址的指向:Array2是6个int类型的数组,每个int占4字节,所以Array2[6]的地址刚好等于Array3[0]的起始地址(&Array2[0] + 6*sizeof(int) = &Array3[0])。

  • ModifyArray的操作与栈帧影响:在ModifyArray函数中,你给ptr3[0]到ptr3[3](也就是Array3[0]到Array3[3])赋值。更关键的是,函数调用过程中的栈帧操作可能修改了这个位置的值:比如函数里的循环变量i是局部变量,会被分配在栈上,如果i的位置刚好和Array2[6]重叠,进入函数时i被初始化为0,函数返回时编译器的栈帧清理操作可能把这个位置重置为0;或者函数调用时保存寄存器、传递参数的操作,刚好把该位置覆盖成了0。

但无论具体是哪种情况,这都只是你当前编译环境下的偶然现象。如果你换用不同的编译器(比如Clang vs GCC)、调整优化级别(比如-O2)、或者改变数组的声明顺序,这个结果很可能就会变成随机值,甚至程序崩溃。

记住:未定义行为的结果永远不可依赖,你应该始终避免越界访问数组。

内容的提问来源于stack exchange,提问作者mrmistermistr

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.08 12:57:38