指针算法是否仍在数组外工作?

时间:2012-08-24 03:47:24

标签: c arrays pointers language-lawyer

我总是在读取指针算法的定义,只要你不离开数组的边界即可。我不确定我完全理解这意味着什么,我有点担心。因此这个问题。

假设我从一个指向数组开头的指针开始:

int *p = (int*) malloc(4 * sizeof(int));

现在我创建两个位于数组范围之外的新指针:

int *q = p + 10;
int *r = p - 2;

现在,指针q-10q-9,...,r+2r+3等都位于数组的边界内。它们有效吗?例如,r[3] 保证可以提供与p[1]相同的结果吗?

我做了一些测试,但它确实有效。但我想知道这是否适用于通常的C规范。具体来说,我使用的是Visual Studio 2010,Windows,而且我使用的是原生C(非C ++)编程。我被覆盖了吗?

3 个答案:

答案 0 :(得分:9)

你正在做的是你正在使用的实现,以及最流行的实现,但它不符合C.正如克里斯所引用,

  

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

未定义的事实在未来可能会变得越来越重要,使用更先进的静态分析,允许编译器将此类代码转换为致命错误而不会产生运行时成本。

顺便说一句,减去不在同一个数组中的指针未被定义的历史原因是分段内存(想想16位x86;那些熟悉它的人会想到“大”内存模型)。虽然指针可能涉及段和偏移组件,但编译器可以仅对偏移组件执行算术以避免运行时成本。这使得不在同一段中的指针之间的算术无效,因为差异的“高部分”丢失了。

答案 1 :(得分:5)

根据C11标准,§6.5.6/ 8(我在上下文中放置了第一部分):

  

当指针中添加或减去具有整数类型的表达式时   ...
  如果指针操作数和结果都指向同一个数组对象的元素,或者指向数组对象的最后一个元素,则评估不应产生溢出;否则,行为未定义。

因此,数组之外的结果而不是结束的结果是未定义的行为。

答案 2 :(得分:-1)

“是”您提到的条件包含在规格中。


    int *r = p - 2; 

r是数组p的边界外,评估结果是将位置分配给r,在p的地址之后/之前的2个int位置。

`r[3]` is simply the "4th" int position after the address of r