在C语言中,指向同一数组不同元素的指针相减是合法的吗?

3

在C语言中,指针相减并不总是指向同一数组的不同元素,这种做法是否有效?

根据C标准,下面这样的操作是否保证有效?我模糊地记得读过这是无效的。

int * a;
int * b;
a = (int*) 100;
b = (int*) 200;
printf("%d\n", b-a);

这会给我25吗?


1
从技术上讲,即使将随机整数分配给指针,在第一时间也不是有效的标准C。 - Random832
1
@Random832:这取决于你所说的“有效”是什么意思。这不是未定义行为。[N1570]6.3.2.3p5:“整数可以转换为任何指针类型。除非有先前规定,否则结果是实现定义的,可能没有正确对齐,可能指向不属于引用类型的实体,并且可能是陷阱表示。”但这很可能是无意义的。 - Keith Thompson
@KeithThompson 谢谢。看到你在 C 控制方面的能力,我不得不问一下,你和 Ken Thompson 有关系吗?开个玩笑。 - disputedbug
@KeithThompson:实际上应该是 printf("%td\n", b - a); - mk12
@Mk12:正确的(假设你的实现支持它)。 - Keith Thompson
显示剩余2条评论
4个回答

6
从C规范的附录J.2“未定义行为”中可以得知:
如果一个指针不指向同一个数组对象或者指向该数组对象的下一个位置,则进行减法操作时会出现未定义行为。
在6.5.6“加法运算符”的第9段中,规定两个指针相减时必须满足以下条件:两个指针都指向同一个数组对象的元素,或者其中一个指针指向该数组对象的最后一个元素后面一个位置。其结果是两个数组元素之间下标的差值。
综上所述,你的示例代码可能会导致未定义行为。但在大多数系统上,该操作不会出错。建议将printf格式更改为%td,以表明您正在打印ptrdiff_t类型。

4

这是未定义行为。

首先,那些指针并没有指向你拥有的内存。

你只能对指向同一数组内部(或者数组末尾后一个位置)的指针进行减法操作。

当然,在大多数编译器上它可能会正常工作,并且你会得到25,因为在你的平台上sizeof(int) == 4。如果它们是char *,你会得到100。(可能会崩溃,这就是未定义行为的美妙之处)。


0
即使标准没有承诺定义行为,结果是正确的。在您的架构中,整数需要4个字节。因此,差异给出了两个指针之间的整数值数量。您可以将差异用作数组中的索引或偏移量。出于同样的原因。
  int *p = (int*) 100;
  p++;

将导致p=104。


0

当然是未定义的。减去两个任意指针(视为整数)甚至不能保证是您对象大小的倍数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接