C++固定长度数组越界访问无报错运行相关问题咨询
首先给你明确一个C原生数组的核心底层逻辑:C的原生数组本质上只是一块连续内存的起始地址标记,编译器只会在你定义数组时帮你申请对应大小的内存,不会在你后续操作数组时主动检查你访问的位置是否在合法范围内。
接下来逐个回答你的问题:
1. 数组大小固定为10个元素,为什么可以给索引为15的位置赋值?
你写arr_[15]的时候,编译器只会把它翻译成「从arr_指向的内存起始地址,往后偏移15个int类型的长度,得到一个新的内存地址,然后往这个地址里写入555」。整个过程没有任何步骤会检查这个偏移后的地址是不是在你最初申请的10个元素的范围内,只要这个地址是你的程序有权限访问的,就不会报错,自然可以赋值成功。
2. 数组是连续分配的内存块,为什么可以跳出数组范围、跳过中间索引给其他位置赋值?
和上面的逻辑一致,数组的[]运算符只负责计算偏移后的内存地址,不管你偏移多少、有没有跳过中间的位置,只要最终的地址是可访问的,就能正常读写。你申请的10个元素的连续内存,只是你有明确所有权的区域,地址在这之外的内存只要有权限就能碰,和你之前申请的连续内存没有绑定关系。
3. 索引11和12处的输出值来源于哪里?
这些位置属于你没有申请的内存区域,里面的值完全是不确定的:
- 可能是程序运行时存储其他临时变量(比如你代码里的i)的内存,也可能是函数运行时的临时标记信息
- 也可能是之前其他程序使用这块内存时留下的残留数据
不同机器、不同编译器、甚至同一台机器多次运行同一段代码,这些位置的值都可能不一样,你第一次运行时前4个合法索引都输出奇怪的大数字,就是因为越界操作破坏了原本arr_数组里存储的正常数据,属于典型的未定义行为,出现任何结果都符合C++的规则。
4. 这是否意味着C++不像Java和Python那样会检查ArrayOutOfIndex错误?
是的,这是C的设计取舍:为了最大化运行性能,原生数组默认完全不做边界检查,把检查边界的责任完全交给开发者自己。
如果你需要边界检查的功能,可以用C标准库提供的std::array容器,调用它的at()方法访问元素时,就会像Java、Python一样主动做边界检查,越界时会抛出异常。
5. 为什么sizeof计算数组的大小还是10?
sizeof是编译阶段就计算完成的常量,你定义int arr_[10]的时候,编译器就已经记录了这个数组占用的总字节数是10 * sizeof(int),这个值是固定的,不会因为你后续运行时越界访问就发生改变。你运行时的越界操作是程序跑起来之后的行为,不会反过来修改编译阶段就确定好的数组大小信息。
内容的提问来源于stack exchange,提问作者Harsh

