3

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

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

   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

我认为同样的问题应该对 C++ 有效

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

4

1 回答 1

4

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

仅在 C 中:鉴于它a[i]与 相同*(a + i),并且&*p始终只是p没有评估*p,因此 5 应该始终没问题,尽管您是对的,C89 没有指定这一点,而这只是在 C99 中添加的。(这在 C++ 中完全不是这样,在 C++ 中,运算符可以被重载,并且没有提到组合&and *。)

从 n1570(草案到 C11),在 6.5.6 加法运算符的第 8 段中:

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

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

于 2012-09-30T20:57:39.823 回答