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

usr*_*usr 2 c pointers c11

考虑一下代码片段:

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

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

   return 0;
}
Run Code Online (Sandbox Code Playgroud)

指针的评估++p是不正确的?

C标准(C11,6.5.6)允许评估指向数组对象的一个末端的指针?这是否也适用于非数组对象?

usr*_*usr 9

++p上述程序中的编号是明确的.但*p=5;导致未定义的行为.

C标准规定

C11草案,6.5.6添加剂操作员,第7页

出于这些运算符的目的,指向不是数组元素的对象的指针与指向长度为1的数组的第一个元素的指针的行为相同,其中对象的类型为其元素类型.

这使得我们可以考虑int iint i[1];当对象上执行指针运算i和6.5.6,P8如下:

[..]如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出; 否则,行为未定义.如果结果指向数组对象的最后一个元素之后,则不应将其用作* 已计算的一元运算符的操作数.

所以评估&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.
Run Code Online (Sandbox Code Playgroud)

但是,这仅适用于阵列的一个结尾.例如,以下第二个增量是未定义的:

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.
Run Code Online (Sandbox Code Playgroud)