是比较指针一个元素超过数组末尾明确定义的吗?

Win*_*ter 4 c arrays pointers undefined-behavior

我通过这个问题了解到,递增NULL指针或递增超过数组的末尾并不是明确定义的行为:

int* pointer = 0;
pointer++;

int a[3];
int* pointer2 = &a[0];
pointer2 += 4; 
Run Code Online (Sandbox Code Playgroud)

但是如果指向无效位置的指针仅用于比较并且从未访问过他位置的内存?

例:

void exampleFunction(int arrayLen, char** strArray)
{
    for(char** str = strArray; str < strArray + arrayLen; str++) //or even str < &strArray[arrayLen]
    {
        //here *str is always a pointer to the first char of my string
    }
}
Run Code Online (Sandbox Code Playgroud)

在这里,我将指针与一个元素超过数组末尾的指针进行比较.这是明确定义的行为吗?

dbu*_*ush 6

与指针相比,可以很好地定义一个超过数组末尾的指针.但是,您pointerpointer2示例是未定义的,即使您对这些指针完全没有任何帮助.

指针可以指向超过数组末尾的一个元素.该指针可能不会被解引用(否则这将是未定义的行为),但可以与数组中的另一个指针进行比较.

C标准的第6.5.6节说明了关于指针添加的以下内容:

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

关于指针比较,第6.5.8节说明如下:

5比较两个指针时,结果取决于指向的对象的地址空间中的相对位置.如果两个指向对象类型的指针都指向同一个对象,或者两个指针都指向同一个数组对象的最后一个元素,则它们相等.如果指向的对象是同一聚合对象的成员,则指向稍后声明的结构成员的指针比指向结构中先前声明的成员的指针大,指向具有较大下标值的数组元素的指针比指向同一数组的元素的指针大.具有较低的下标值.指向同一个union对象的成员的所有指针都比较相等.如果表达式P指向数组对象的元素,并且表达式Q指向同一数组对象的最后一个元素,则指针表达式Q + 1比较大于P.在所有其他情况下,行为是未定义的.

在这种情况下pointer1,它开始指向NULL.增加此指针会调用未定义的行为,因为它不指向有效对象.

因为pointer2,它增加了4,将两个元素放在数组的末尾,而不是一个,所以这又是未定义的行为.如果它增加3,行为将被明确定义.

  • “一次通过”规则不是也适用于非数组对象吗?`int x; int *p = &amp;x+1;` (2认同)
  • @chux你可能是对的。第 6.5.8 节第 4 部分说 *“就这些运算符的目的而言,指向不是数组元素的对象的指针的行为与指向长度为 1 且类型为该数组的第一个元素的指针相同。 object 作为其元素类型。*”第 6.5.6 节第 7 部分具有相同的措辞。 (2认同)