计算指向未初始化内存的指针是 C 中的未定义行为吗?

Byt*_*ter 3 c pointers pointer-arithmetic undefined-behavior

如果我理解正确的话,这个程序在 C++ 中具有未定义的行为,因为中间值p + 1是指向未初始化内存的指针:

int main () {
    int x = 0;
    int *p = &x;
    p = p + 1 - 1;
    *p = 5;
}
Run Code Online (Sandbox Code Playgroud)

如果void放入 的main参数列表中(按照 C 语法的要求),它在 C 中是否也是未定义的行为?

Vla*_*cow 8

不存在未定义的行为。您可以将单个对象视为具有一个元素的数组。使用指针算术,指针可能指向数组最后一个元素之后的元素,因此此语句

p = p + 1 - 1;
Run Code Online (Sandbox Code Playgroud)

是正确的。

来自 C 标准(6.5.6 加法运算符)

7 就这些运算符而言,指向不是数组元素的对象的指针的行为与指向长度为 1 的数组的第一个元素的指针相同,且对象的类型作为其元素类型。

  1. ...此外,如果表达式 P 指向数组对象的最后一个元素,则表达式 (P)+1 指向数组对象的最后一个元素后一位,如果表达式 Q 指向数组对象的最后一个元素后一位数组对象,表达式(Q)-1指向数组对象的最后一个元素。

注意这一点

  1. ...如果指针操作数和结果都指向同一个数组对象的元素,或者超过数组对象的最后一个元素,则求值不会产生溢出;否则,行为是未定义的。

  • @alfC 重读我的答案中提供的标准中的引用#7。 (2认同)
  • @alfC:正如引用的那样,C 标准表示,在指针算术中,单个对象充当一个元素的数组,并且您可以添加该对象以创建指向数组最后一个元素之外的元素的指针。这是决定性的;定义该行为是因为 C 标准定义了它。 (2认同)