数组指针运算 - 法律和未定义行为 [英] Array-pointer arithmetic - legal and undefined behaviour

查看:130
本文介绍了数组指针运算 - 法律和未定义行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我问自己,如果这些线code的可以在C和用C产生不确定的行为++。
我试着回答每一个点读什么标准说有关数组下标(C 6.5.6 - 8)。我没有贴全款,因为它是pretty长。


  

此外,如果前pression P 指向最后一个
  数组对象的元素,前pression (P)+1 点中的一个过去的最后一个元素
  数组对象,如果前pression 问:点中的一个过去的数组对象的最后一个元素,
  恩pression (Q)-1 指向数组对象的最后一个元素。如果这两个指针
  操作数和结果指向相同的数组对象的元素,或者一个过去的最后
  数组对象的元素,该评估也不得产生溢出;否则,
  行为是不确定的。如果结果点中的一个过去的阵列>对象的最后元件,它
  不得用作评估一元 * 运算符的操作数。


  1 int类型的[10];
   2 INT B = A [9]; // 好
   3 INT C = A [10]; // UB
   4 INT * D =(A + 10); // 好
   5 INT * E =&放大器;一个[10]; // OK从C99(安培;和[]被忽略,指针不deferenced),//在UB pre C99
   6为int * F =&放大器;一个[11]; //从C99,UB确定在pre C99
      INT * G =一;
   7 INT * H = G + 15; // 好

我认为同样的aswers应该是有效的C ++

难道这些行有效的C和C ++中,有我误解了标准?


解决方案

无论是6还是7是有效的,因为他们没有一个现有的阵列(包括一个过去的非结束指针)内执行指针运算。一切是基本上是正确的。

在仅C:鉴于 A [I] *(A + I),和&放大器; * p 永远只是 p 没有评估 * p 5应始终很好,虽然你说得对,C89没有规定这一点,这是只有在C99增加。 (这是不正确的在C ++中,在运算符可以重载都并没有结合提&安培; *

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


  

[...]如果指针操作数和结果都[的点+ N ]指向同一个数组对象的元素,或者一个过去的最后一个元素数组的对象,该评估也不得产生溢出;否则,其行为是不确定的。 [...]


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

I was asking myself if these line of code could produce undefined behaviour in C and in C++. I tried to answer to each point reading what the standard says about array subscripting (C 6.5.6 - 8). I didn't posted the entire paragraph because it is pretty long.

Moreover, if the expression P points to the last element of an array object, the expression (P)+1 points one past the last element of the array object, and if the expression Q points one past the last element of an array object, the expression (Q)-1 points to the last element of the array object. If both the pointer operand and the result point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. If the result points one past the last element of the array >object, it shall not be used as the operand of a unary * operator that is evaluated.

   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

I think that the same aswers should be valid for C++

Are these lines valid in C and in C++, have I misunderstood the standard?

解决方案

Neither 6 nor 7 are valid, because they do not perform pointer arithmetic inside an existing array (including the one-past-the-end pointer). Everything else is essentially correct.

In C only: Given that a[i] is identical to *(a + i), and &*p is always just p without evaluating *p, 5 should always be fine, although you're right that C89 does not specify this and this was only added in C99. (This is not true at all in C++, where operators can be overloaded and there is no mention of combining & and *.)

From n1570 (draft to C11), in paragraph 8 of 6.5.6 Additive operators:

[...] If both the pointer operand and the result [of P + N] point to elements of the same array object, or one past the last element of the array object, the evaluation shall not produce an overflow; otherwise, the behavior is undefined. [...]

C++ contains very similar wording (e.g. C++11, 5.7/5).

这篇关于数组指针运算 - 法律和未定义行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆