C语言数组越界元素表现差异的原因解析
数组越界访问为何出现三种不同结果?
当尝试打印数组索引范围外的数组元素的地址和值时,为何部分元素会返回以下三种结果:
- (nil)指针
- 数组中其他元素的地址
- 随机地址(推测是物理内存地址)
测试程序
#include <stdio.h> int main(){ int arr[5]; arr[0]=1; arr[1]=2; arr[2]=3; arr[3]=4; arr[4]=5; printf("%d\t-\t%p\n", arr[0], arr[0]); printf("%d\t-\t%p\n", arr[1], arr[1]); printf("%d\t-\t%p\n", arr[2], arr[2]); printf("%d\t-\t%p\n", arr[3], arr[3]); printf("%d\t-\t%p\n", arr[4], arr[4]); printf("%d\t-\t%p\n", arr[5], arr[5]); printf("%d\t-\t%p\n", arr[6], arr[6]); printf("%d\t-\t%p\n", arr[7], arr[7]); printf("%d\t-\t%p\n", arr[8], arr[8]); printf("%d\t-\t%p\n", arr[9], arr[9]); printf("%d\t-\t%p\n", arr[10], arr[10]); printf("%d\t-\t%p\n", arr[11], arr[11]); }
输出结果
1 - 0x1 2 - 0x2 3 - 0x3 4 - 0x4 5 - 0x5 0 - (nil) // (nil is printed here) 1367157456 - 0x517d2ad0 // (random address and value) 32628 - 0x7f74 // (random address and value, which should have been adjacent, I think) 1 - 0x1 // (address and value of other element in array) 0 - (nil) // (here too, nil is printed) 1365029450 - 0x515cb24a 32628 - 0x7f74
编译与运行环境
- 使用
gcc编译,命令:gcc ./temp.c - x86 64位Linux机器
问题解析
首先要明确:你的代码存在核心错误——你用%p打印的是数组元素的值,而非元素的地址。正确打印元素地址的写法应该是printf("%d\t-\t%p\n", arr[i], &arr[i]);,当前写法是把整数类型的元素值强制转换成指针类型输出,这和你想观察的“数组元素地址”完全不是一回事。
抛开代码错误,数组越界访问在C语言中属于未定义行为——C标准没有规定这种情况下程序的运行逻辑,编译器、操作系统可以做出任意处理,所有结果都不可预测。结合内存布局,你看到的三种现象可以这样解释:
- 输出(nil):越界访问到的内存区域恰好存储了0值,用
%p打印这个0值时,会被解析为空指针,最终显示(nil)。 - 出现数组其他元素的值:越界访问的内存位置刚好和数组内某个元素的存储区域重叠(比如栈内存布局导致越界后绕回数组区域),或者恰好读取到了和数组元素相同的随机值。
- 随机地址/值:越界访问到了栈上的其他变量、函数返回地址、栈帧信息,或者堆/全局区的内存,这些区域的值是不确定的,看起来像“随机值”——注意这不是物理内存地址,Linux下程序使用的都是虚拟内存地址。
内容的提问来源于stack exchange,提问作者Thunder
相关产品推荐
相关产品推荐

