指针算术(char*) &a[1] - (char *)&a[0] == 4

3
如果a是一个int数组,(char*) &a[1] - (char *)&a[0]等于4,而&a[1] - &a[0]等于1。为什么会这样呢?

2
4字节对齐? 在指针转换后,第一个情况可以获得正确的信息。 - Eddy_Em
2
指针算术是根据所指向的对象的大小来计算的。 - Barmar
所以一旦进行了强制转换,编译器就认为这两个元素相隔一个字节,这种差异意味着它们之间有4个字符,因此返回值是4。而在非强制转换的情况下,编译器认为这两个元素相隔4个字节,但它们实际上只相隔1个int元素,因此返回值是1? - drerD
这是指针算术,就像指针相减时发生的情况一样。 - moeCake
3个回答

5
指针运算操作的是指向的数据结构的大小。这是因为如果我这样做:
int array[10] ;
int * p = array ;

p ++ ;

我希望p指向第二个整数,而不是在两个元素之间的某个内存处。

因此,&a[1]&a[0]相距四个字节,但是询问它&a[1] - &a[0]会问有多少个int之间的距离。当你将它转换为char时,你要求用char的大小来计算数学。


3
当你执行

&a[1] - &a[0]

由于a是一个整型数组,会隐式地假定为int*类型的指针,也就是说

(int *)&a[1] - (int *)&a[0]

因此,由于两者均为指向 int 类型的指针,它们之间的差异为 1。

但是当您进行以下操作时-

(char*) &a[1] - (char *)&a[2]

假设在你的编译器上int占用4个字节,char占用1个字节,那么a数组中每个元素都是int类型,每个int类型占用4个字节,所以它们之间的差距为4。

0
这是程序员常见的问题,把指针仅仅看作地址。这是错误的方法。为了编译器能够创建适当的底层代码,它必须知道关于指针的一些更多信息而不仅仅是它所指向的内存位置。那些额外的信息就是指针指向的对象的大小。所有这些都包含在指针类型中,并且对于指针算术运算是必要的。例如:
int a[25] ;
int *i_ptr = a;

printf("address of 1st element %d\n", a);
printf("address of 1st element %d\n", &a[0]);

// address of first element + sizeof(int)
printf("address of 2nd element %d\n", a+1);

// address of first element + sizeof(int)    
printf("address of 2nd element %d\n", &a[1]);

// this one is tricky
// address of first element + sizeof(25*int) ie sizeof(the whole array)
printf("address of JUST AFTER THE ARRAY %d\n", &a+1);

最后一个问题非常棘手,大多数程序员甚至不知道它的存在。虽然 a 指向数组的第一个元素,并且具有数组元素的类型,但 &a 则完全不同。它还保留了数组第一个元素(即数组开头)的地址,但其类型不同,表明编译器对其进行指针算术运算时将基于数组大小而不是元素大小。

给出:

address of 1st element 2881388               +0
address of 1st element 2881388               +0
address of 2nd element 2881392               +4
address of 2nd element 2881392               +4
address of JUST AFTER THE ARRAY 2881488    +100

每次使用&运算符获取某个东西的地址时,它都有与之关联的类型,允许以后使用该指针类型进行计算。
请记住,有一个指针void *,它没有任何与之关联的类型信息,您无法对其执行算术运算。

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