C语言pointer-to-array申请超量内存后访问额外元素是否属未定义行为
C语言指向数组的指针超范围访问合法性解答
结论
你给出的示例代码触发未定义行为(Undefined Behavior, UB),即便在GCC环境下编译运行符合预期,也不代表代码是安全、可移植的。
原因解释
根据C标准的指针运算规则:
int (*foo)[10]中foo的类型是「指向包含10个int元素的数组的指针」,对其解引用得到的*foo类型为int[10](长度为10的int数组)。- 数组类型在参与指针运算时会隐式退化为指向首元素的
int*指针,该指针对应的合法访问范围仅为0 ~ 9的下标区间。 - C标准明确规定:指针算术运算仅允许在同一块数组的有效范围内(含数组末尾后1个元素的占位地址)进行,超出该范围的运算和访问直接判定为未定义行为。
你示例中(*foo)[15]、*(*foo +16)的访问下标已经超出*foo对应的10个元素的合法范围,哪怕malloc实际分配了更大的内存,也不符合标准的类型约束要求。
为什么GCC下运行正常?
当前主流编译器(包括GCC)在低优化等级下,不会对这类指针访问做过于激进的类型边界检查和优化,因此会按照内存地址直接读写,刚好得到预期结果。但如果开启-O2/-O3等高优化等级,编译器可能会基于「(*foo)[n]的n最大为9」的类型信息做优化,直接删除超出范围的访问代码、返回错误值甚至触发崩溃,所有这些异常表现都是符合C标准要求的。
合法写法参考
如果需要动态分配20个int的内存并安全访问,推荐两种写法:
- 直接用一级指针指向分配的int数组:
int *foo = malloc(sizeof(int) * 20); foo[15] = 100; // 完全合法,访问范围在分配的20个元素内
- 如果必须使用指向数组的指针,确保声明的数组大小与分配大小匹配,或做合法的指针类型转换后再访问超出原数组范围的内存。
内容的提问来源于stack exchange,提问作者Jackson Allan
相关产品推荐
相关产品推荐

