首页 > 解决方案 > 指向内存负地址的 C 编译器行为是什么?

问题描述

在 C 代码段下面编译运行后 p1、p2 的状态是什么?

char *p1 = malloc(5);
char *p2 = p1 - 3;
*p2 = '\0';

标签: cpointers

解决方案


如果您要将此 C 代码直接转换为简单机器上的简单机器代码,char *p2 = p1 - 3;则将设置p2为指向内存中比 更早的三个字节p1,并将*p2 = '\0'零写入不正确的位置。我们不知道那个位置是什么,所以我们不能说效果是什么。

但是,现代编译器通常不会将 C 代码直接转换为简单的机器代码。他们解释 C 代码并对其进行复杂的优化。因此,了解发生了什么需要使用 C 标准或正在使用的编译器的文档。

关于这段代码,C 标准告诉我们什么?对于p1 - 3,适用于 C 2018 6.5.6 8 中的指针加法规则:

当一个整数类型的表达式被添加到一个指针或从一个指针中减去时,...... 如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。

因为p1指向由 提供的对象(可以用作数组)的元素mallocp1 - 3而不指向该数组的元素,所以 C 标准没有定义行为。因此,如果我们以C标准作为理解的基础,一旦p1 - 3被评估,我们就不能说程序的行为或状态p1是什么p2


推荐阅读