数组指针算法 - 合法和未定义的行为

时间:2012-09-30 20:54:50

标签: c++ c arrays pointers undefined-behavior

我问自己这些代码行是否会在C和C ++中产生未定义的行为。 我试图回答每一点,阅读标准关于数组下标的内容(C 6.5.6 - 8)。我没有发布整段,因为它很长。

  

此外,如果表达式P指向最后一个   数组对象的元素,表达式(P)+1指向一个超过最后一个元素的元素   数组对象,如果表达式Q指向一个数组对象的最后一个元素,   表达式(Q)-1指向数组对象的最后一个元素。如果两个指针   操作数和结果指向同一个数组对象的元素,或者指向最后一个数组对象的元素   数组对象的元素,评估不得产生溢出;否则,   行为未定义。如果结果指向一个超过数组>对象的最后一个元素,那么它   不得用作被评估的一元*运算符的操作数。

   1  int a[10];
   2  int b = a[9]; // ok
   3  int c = a[10]; // UB
   4  int* d = (a + 10); // ok
   5  int* e = &a[10]; // ok from C99 (& and [] are ignored, pointer is not deferenced), // UB in pre C99
   6  int* f = &a[11]; // ok from C99, UB in pre c99 
      int* g = a;
   7  int* h = g + 15; // ok

我认为相同的aswers应该对C ++有效

这些行在C和C ++中是否有效,我误解了标准吗?

1 个答案:

答案 0 :(得分:4)

6和7都不是有效的,因为它们不在现有数组内执行指针运算(包括一个过去的指针)。其他一切基本上都是正确的。

仅限C:假设a[i]*(a + i)相同,而&*p始终只是p而不评估*p,则5应该始终没问题虽然你是对的,C89没有指定这个,但这只是在C99中添加的。 (在C ++中根本不是这样,运算符可能会被重载,并且没有提到将&*组合在一起。)

从n1570(草案到C11),6.5.6添加剂操作符的第8段:

  

[...]如果指针操作数和[P + N]的结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。 [...]

C ++包含非常相似的措辞(例如C ++ 11,5.7 / 5)。