C ++是否合法地使用超过数组末尾2或更多的地址?

时间:2014-01-01 22:32:57

标签: c++ arrays

来自Take the address of a one-past-the-end array element via subscript: legal by the C++ Standard or not?

似乎有一种语言特定于将一个的地址多于数组末尾。

为什么 2 2,000,000 在结束时会出现问题,如果它没有被解除引用?

看一些简单的循环:

int array[];
...
for (int i = 0: i < array_max; ++i)
{
       int * x = &array[i *2];      // Is this legal
       int y=0;
       if (i * 2 < array_max)       // We check here before dereference
       {
              y = *x;               // Legal dereference
       }
       ...
}

为什么或在什么时候这变得未定义,在实践中它只是将ptr设置为某个值,为什么如果它没有被重新引用它将是未定义的?

更具体地说 - 除了预期会发生什么之外,还有什么例子?

3 个答案:

答案 0 :(得分:8)

使用超出数组末尾的地址的关键问题是分段体系结构:您可能溢出指针的可表示范围。现有规则已经产生了一定程度的痛苦,因为这意味着最后一个对象不能正好在一个段的边界上。但是,形成这个地址的能力已经确立。

答案 1 :(得分:4)

由于array[i *2]等同于*((array) + (i*2)),我们应该查看指针添加的规则。 C ++11§5.7说:

  

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

所以你有未定义的行为,即使你没有对指针执行间接(更不用说你执行间接,因为我在开头给出的表达式等价)。

答案 2 :(得分:3)

  

在实践中它只是将ptr设置为某个值

理论上,不允许使用指向某处无效的指针。

指针整数:它们是指向其他内容或无效的内容。

您不能将它们设置为您喜欢的任何数字。

  

在这个例子中,只有赋值,然后是限定的dereferrencing - 该值仅在验证时使用,问题是为什么值的设置是个问题?

是的,你必须非常不幸遇到这样做的实际后果。 “未定义的行为”意味着“总是崩溃”。为什么标准实际上要求这种操作的语义?您认为这种语义应该是什么?