关于指针比较,标准中的措辞比较奇怪

§6.5.8\ 6 (关于>,<, =)

如果表达式P指向数组对象的元素并且表达式Q指向同一数组对象的最后一个元素,则指针表达式Q + 1比P大。 在所有其他情况下,行为未定义。

上面的几节,§6.5.8,它解释了基本上,指针算法在数组上按预期工作。 这是int a[3]; int *p = a; int *q = &a[2]; //qp == 3 int a[3]; int *p = a; int *q = &a[2]; //qp == 3 int a[3]; int *p = a; int *q = &a[2]; //qp == 3有效。 但是,当我读到上面的q > p是UB。

我错过了什么?

首先,你引用了段落的一部分,第一部分解释了这个引用的内容,我在这里包含了段落:

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

基本上,您引用的位指的是通常指针必须始终指向独立对象,对象数组的元素或超过对象数组末尾的指针。 正如您所看到的,通常递增一个已指向数组最后一个元素的指针会产生一个无效指针,实际上该标准中的指针绝不能被取消引用,但是它可以用于一个特殊情况,即它可以设置或与另一个指针进行比较。

这在一个程序中非常有用,在该程序中,您递增一个指针,然后检查它是否超过了数组的末尾,如果它已经结束则终止。 例如。

 int foo = 0; int ArrSize = 6; int bar[ArrSize]; while(foo < ArrSize) { foo++; printf("%d", bar + 3 < bar + foo); } 

即使在foo指向超出数组末尾的最后一种情况下,也是合法的。

请注意,这个例子非常有用,但certificate了这一点。

如果不符合此规则,则此程序将是未定义的行为。