我总是在读取指针算法的定义,只要你不离开数组的边界即可。我不确定我完全理解这意味着什么,我有点担心。因此这个问题。
假设我从一个指向数组开头的指针开始:
int *p = (int*) malloc(4 * sizeof(int));
现在我创建两个位于数组范围之外的新指针:
int *q = p + 10;
int *r = p - 2;
现在,指针q-10
,q-9
,...,r+2
,r+3
等都位于数组的边界内。它们有效吗?例如,r[3]
保证可以提供与p[1]
相同的结果吗?
我做了一些测试,但它确实有效。但我想知道这是否适用于通常的C规范。具体来说,我使用的是Visual Studio 2010,Windows,而且我使用的是原生C(非C ++)编程。我被覆盖了吗?
答案 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