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

时间:2017-07-26 19:11:20

标签: c arrays pointers undefined-behavior

我通过this question了解到,递增NULL指针或递增超出数组末尾的行为并不明确:

getItemInfo(itemID: string): ItemInfoModel {

 var subscription = this.db.list('/itemInfo/', { query: {  orderByChild: 'item',  equalTo: itemID  }})
 .subscribe(itemInfo => {
      let i: ItemInfoModel = itemInfo.val();
      this.itemInfo = i;
    });
  subscription.unsubscribe();
  return this.itemInfo;
}

但是如果指向无效位置的指针仅用于比较并且永远不会访问其位置的内存?

示例:

int* pointer = 0;
pointer++;

int a[3];
int* pointer2 = &a[0];
pointer2 += 4; 

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

1 个答案:

答案 0 :(得分:6)

比较指针一个步骤超过数组末尾的定义很明确。但是,您的pointerpointer2示例未定义,即使您对这些指针完全没有任何依据。

指针可以指向超出数组末尾的一个元素。该指针可能不会被解引用(否则可能是undefined behavior),但可以与数组中的另一个指针进行比较。

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

  

8 如果指针操作数和结果都指向同一个数组对象的元素,或者超出数组最后一个元素的元素   对象,评估不得产生溢出; 否则,   行为未定义。如果结果指向最后一个元素   对于数组对象,它不应该用作一元*的操作数   被评估的运算符。

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

  

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

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

对于pointer2,它增加了4,将两个元素放在数组的末尾,而不是一个,所以这又是未定义的行为。如果它增加了3,那么行为就会很明确。