C语言中给数组指针少分配内存仅访问合法范围是否属于未定义行为?
问题解答
1. 你给出的示例属于明确的未定义行为,哪怕仅访问前5个元素
核心原因在于指针类型的约束:
int (*foo)[10]的语义是「指向包含10个int元素的数组的指针」,当你执行*foo解引用操作时,C标准要求该指针必须指向一个合法、完整的int[10]类型对象,否则解引用操作本身就触发未定义行为。malloc(sizeof(int)*5)仅分配了能容纳5个int的内存,完全不足以承载一个int[10]类型的对象,因此后续哪怕只写(*foo)[0] = 1;这类仅访问前5个元素的代码,第一步的*foo解引用已经违反了标准要求,和后续下标的访问范围无关。- 如果你只是想分配5个int的内存且按数组下标访问,合法写法是直接使用普通int指针:
int *p = malloc(sizeof(int)*5);,此时访问p[0]~p[4]完全符合标准规定。
你示例代码的问题简化后如下:
int (*foo)[10]; // 指针的目标类型为长度10的int数组 foo = malloc( sizeof(int) * 5 ); // 分配的内存不满足目标类型的大小要求 // 后续任何对*foo的引用都属于未定义行为
2. 严格别名规则冲突的前提不成立
因为示例代码本身已经触发了未定义行为,不需要再讨论后续访问其他对象是否触发严格别名的问题。
如果退一步假设你使用合法的普通int指针访问越界地址:
- 如果你通过int类型的左值,访问了一个非int类型、也不与int类型兼容的其他对象,会触发严格别名规则冲突,属于未定义行为。
- 哪怕访问的目标对象是int类型,访问不属于当前内存分配范围的地址本身也属于未定义行为,和别名规则无关。
内容的提问来源于stack exchange,提问作者Jackson Allan
相关产品推荐
相关产品推荐

