由C ++标准或不合法:以通过下标一过去,中高端数组元素的地址? [英] Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?

查看:133
本文介绍了由C ++标准或不合法:以通过下标一过去,中高端数组元素的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经看到了,现在断言几次,以下code不被C ++标准允许的:

I have seen it asserted several times now that the following code is not allowed by the C++ Standard:

int array[5];
int *array_begin = &array[0];
int *array_end = &array[5];

&放大器;?阵列[5] 法律C ++ code在这方面

Is &array[5] legal C++ code in this context?

我想与该标准如果可能的参考答案。

I would like an answer with a reference to the Standard if possible.

这也将是有趣的知道,如果它符合C标准。而如果它不是标准的C ++,为什么决定做出从阵列+ 5 &放不同的方式对待它;数组[4] + 1

It would also be interesting to know if it meets the C standard. And if it isn't standard C++, why was the decision made to treat it differently from array + 5 or &array[4] + 1?

推荐答案

您的例子是合法的,但仅仅是因为你没有实际使用的是出界的指针。

Your example is legal, but only because you're not actually using an out of bounds pointer.

让我们处理出界球的第一个(因为这就是我最初间preTED你的问题之前,我注意到示例使用了一个过去的最末尾指针代替):

Let's deal with out of bounds pointers first (because that's how I originally interpreted your question, before I noticed that the example uses a one-past-the-end pointer instead):

在一般情况下,你甚至不允许的创建的越界指针。指针必须在阵列内指向一个元素,或者一个过去的结束的。无处。

In general, you're not even allowed to create an out-of-bounds pointer. A pointer must point to an element within the array, or one past the end. Nowhere else.

该指针甚至不允许存在的,这意味着你显然不能解引用它的。

The pointer is not even allowed to exist, which means you're obviously not allowed to dereference it either.

下面就是标准有话要说:

Here's what the standard has to say on the subject:

5.7:5:

当有不可分割的一个前pression
  类型添加到或从一个中减去
  指针,结果具有的类型
  指针操作数。如果指针
  操作数指向的元素
  数组对象,数组大
  够,其结果指向一个
  元件从原来的偏移
  元件,使得的差
  由此而来的标和
  原数组元素等于
  积分前pression。换一种说法,
  如果前pression P指向到第i个
  数组对象的元素时,
  前pressions(P)+ N(等同于
  N +(P))和(P)的N(其中N具有
  值n)指向,分别
  1 +的第n个和i-n个元素
  数组对象,只要他们存在。
  此外,如果前pression P指向
  到一个数组的最后一个元素
  对象,前pression(P)+1点
  1过去阵列的最后一个元素
  对象,并且如果前pression Q分
  1过去一个数组的最后一个元素
  对象,前pression(Q)-1分
  数组对象的最后一个元素。
  如果指针操作数和两
  结果指向相同的元件
  数组对象,或者一个过去的最后一个
  数组对象的元素时,
  评估也不得产生
  溢流; ,否则,行为
  理解过程网络斯内德

When an expression that has integral type is added to or subtracted from a pointer, the result has the type of the pointer operand. If the pointer operand points to an element of an array object, and the array is large enough, the result points to an element offset from the original element such that the difference of the subscripts of the resulting and original array elements equals the integral expression. In other words, if the expression P points to the i-th element of an array object, the expressions (P)+N (equivalently, N+(P)) and (P)-N (where N has the value n) point to, respectively, the i+n-th and i−n-th elements of the array object, provided they exist. 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.

(重点煤矿)

当然,这是用于操作员+。所以,只是可以肯定,这里就是标准说,关于数组下标:

Of course, this is for operator+. So just to be sure, here's what the standard says about array subscripting:

5.2.1:1:

这位前pression E1 [E2] 是相同的(由德网络nition)为 *((E1)+(E2))

The expression E1[E2] is identical (by definition) to *((E1)+(E2))

当然,有一个明显的警告:您的例子没有实际显示一个彻头彻尾的越界指针。它采用的是一过去的结束指针,这是不同的。该指针允许存在(如上面说的),但标准的,据我所看到的,说,大约取消引用它没有。我能找到的最接近的是3.9.2:3:

Of course, there's an obvious caveat: Your example doesn't actually show an out-of-bounds pointer. it uses a "one past the end" pointer, which is different. The pointer is allowed to exist (as the above says), but the standard, as far as I can see, says nothing about dereferencing it. The closest I can find is 3.9.2:3:

[注:例如,在在地址一过去的阵列(5.7)的端部将被认为
  指向可能位于该地址的数组元素类型的一个不相关的对象。末端注意事项】

[Note: for instance, the address one past the end of an array (5.7) would be considered to point to an unrelated object of the array’s element type that might be located at that address. —end note ]

这似乎给我暗示,是的,你可以合法地引用这些,但读取或写入的位置,结果是不确定的。

Which seems to me to imply that yes, you can legally dereference it, but the result of reading or writing to the location is unspecified.

感谢ilproxyil这里纠正的最后一位,回答你的问题的最后一部分:

Thanks to ilproxyil for correcting the last bit here, answering the last part of your question:


  • 阵列+ 5 实际上并不
    解引用什么,它只是
    创建一个指向包含一个过去的结束
    阵列

  • &放大器;数组[4] + 1 指针引用
    阵列+ 4 (这是完全安全的),
    采用该左值的地址,并
    添加一个到该地址,这
    结果在一过去的非结束指针
    (但指针永远不会
    取消引用。

  • &放大器;阵列[5] 取消引用数组+ 5
    (其中据我可以看到的是合法的,
    而导致一个不相关的对象
    数组的元素类型中,作为
    上面说的),然后取
    该元素,这也地址
    似乎很合法的。

  • array + 5 doesn't actually dereference anything, it simply creates a pointer to one past the end of array.
  • &array[4] + 1 dereferences array+4 (which is perfectly safe), takes the address of that lvalue, and adds one to that address, which results in a one-past-the-end pointer (but that pointer never gets dereferenced.
  • &array[5] dereferences array+5 (which as far as I can see is legal, and results in "an unrelated object of the array’s element type", as the above said), and then takes the address of that element, which also seems legal enough.

因此​​,他们不这样做相当同样的事情,但在这种情况下,最终结果是一样的。

So they don't do quite the same thing, although in this case, the end result is the same.

这篇关于由C ++标准或不合法:以通过下标一过去,中高端数组元素的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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