为什么这两个指针减法会给出不同的结果?

时间:2012-02-07 22:44:56

标签: c++

请考虑以下代码:

char* p = new char[2];
long* pi = (long*) p;
assert(p == pi);         // OK

char* p1 = &p[1];
long* pi1 = (long*) p1;
assert(p1 == pi1);       // OK

int d = p1 - p;
int d1 = pi1 - pi;
assert(d == d1);         // No :(

运行后,我得到d == 1d1 == 0,虽然p1 == pi1p == pi(我在调试器中检查了这一点)。这是未定义的行为吗?

4 个答案:

答案 0 :(得分:10)

正如其他人指出的那样,这是未定义的行为。但是,对于您所看到的内容有一个非常简单的解释。

指针之间的区别在于元素的数量,而不是它们之间的字节数。

pi和pi1都指向long,但pi1指向的地址仅比pi大一个字节。假设long是4个字节长,地址的差值1除以元素4的大小为0。

另一种思考方式是你可以想象编译器会生成与此相当的代码来计算d1:

int d1 = ((BYTE*)pi1 - (BYTE*)pi)/sizeof(long).

答案 1 :(得分:5)

如果指针没有指向同一个数组,或者指针是从指向不相关类型的指针进行类型转换,则两个指针之间的区别是未定义的。

此外,差异不是字节数,而是元素数。

在第二种情况下,差异是1个字节,但它除以sizeof(long)。请注意,因为这是未定义的行为,所以这里的任何答案都是正确的。

答案 2 :(得分:2)

重新解释指针的基础类型不会更改其地址。但指针算术会根据指针类型产生不同的结果。所以你在这里描述的是完全正确的,这就是我所期望的。请参阅pointer arithmetics

答案 3 :(得分:0)

它为pi1 - pi执行整数(长)指针算术;

如果p1&p[4],您会看到它为1打印d1,而差异实际为4个字节。这是因为sizeof (long) = 4个字节。