是否正在评估指向未定义对象存储之外的指针?

Is evaluating a pointer that points to beyond an object's storage undefined?

考虑代码片段:

int main(void)
{
   int i = 42;
   int *p = &i;

   ++p; // Is this pointer evaluation undefined?
   *p = 5; // How about this?

   return 0;
}

++p 中指针的求值格式错误?

C 标准 (C11, 6.5.6) 允许评估指向 array 对象的过去一端的指针?这也适用于非数组对象吗?

没有。上面程序中的 ++p 是定义明确的。但是 *p=5; 导致 undefined behaviour.

C 标准规定

C11 草案,6.5.6 加法运算符,p7

For the purposes of these operators, a pointer to an object that is not an element of an array behaves the same as a pointer to the first element of an array of length one with the type of the object as its element type.

这允许我们在对对象i和6.5.6进行指针运算时将int i视为int i[1];,p8如下:

[..]If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array object, it shall not be used as the operand of a unary * operator that is evaluated.

所以 &i+1 的计算在 C 中是明确定义的,无论 i 是否是一个对象数组。但是,取消引用它是未定义的:

int i = 9;
int *p = &i + 1; // Only pointer evaluation done here. Well-defined.
int x = *(p-1); // well defined. p-1 is should be equal to &i as required by 6.5.6, p8
*p = 42; // ill-formed.

int arr[5];
int *q = arr+5; // well-defined. Evaluating one past the end of an array.
*q = 42; //This is undefined.

但是,这仅适用于数组的尾数。例如,下面的第二个增量是未定义的:

int i = 9;
int *p = &i;

++p; // This is OK. Evaluation is allowed.
*p = 5; // This is undefined. Not allowed to de-reference the pointer one past the end.
++p; // This is undefined. `p` now points to two past the end of the object after increment.
*p = 5; // This is undefined.