我在比赛问题文件中找到了这个程序:
#include <iostream>
void main()
{
int a[5] = { 1, 2, 3, 4, 5 };
int *ptr = (int*)(&a + 1);
printf("%d %d ",*(a + 1), *(ptr - 1));
}
输出为2 5
现在当我将第5行更改为int *ptr=(int*)(&a);
和printf("%d %d ",*(a + 1), *(ptr));
输出变为2 1
在第一种情况下,ptr
获得了array+1
的最后一个地址,而在第二种情况下,ptr
获得了相同的数组地址(a
的地址)。
我怀疑为什么当a增加并分配给ptr
并且a
被分配给ptr
而不增加时,此分配会显示不同类型的行为?
答案 0 :(得分:5)
当你获取数组的地址时,你得到一个指向5个整数数组的指针(即int(*)[5]
)。当您递增该指针时,它会移动5个整数的数组大小。所以它指向一系列数组中的下一个数组(如果你实际上有一系列数组)。然后,当您将该指针转换为int*
时,它将成为指向第二个(不存在的)数组的第一个int
的指针,该数组是第一个数组的最后一个元素之后的一个元素。这就是你的第一个例子所发生的事情。
使用第二个示例,您没有递增指向数组的指针,因此当您将其转换为int*
时,它将成为指向数组中第一个int
的指针。
答案 1 :(得分:3)
&a
是指向大小为5的整数数组的指针,而ptr
是int*
。因此,&a + 1
增加int[5]
的大小,而int*
上的指针算术将指针的值更改为sizeof(int)
的倍数。因此,&a + 1
指向5*sizeof(int)
地址a
的地址。将其投放到int* ptr
并执行ptr-1
会为您提供a[4]
的地址。
答案 2 :(得分:2)
&a + 1;
这里,简单a
指的是数组的基地址,即第一个元素的地址。当您说a+1
编译器会将+1
应用于pointer to an int
时。因此,它会增加偏移量,这会使它跳转到下一个整数。
但是,当您说&a
时,它表示该数组元素的地址(类型为int [5]
)。因此,向它添加一个意味着下一个偏移将是该类型的下一个数组,即间接到数组的一个结尾。 在你没有取消引用之前,取一个数组元素的地址是没问题的。