我的字符指针指向无效的值后从int *

我正在学习C编程语言,我刚开始学习数组指针 。 我在这个问题上有问题,我希望那个输出必须是5但是是2 ,谁能解释一下为什么?

 int main(){ int arr[] = {1, 2, 3, 4, 5}; char *ptr = (char *) arr; printf("%d", *(ptr+4)); return 0; } 

假设int是32位(4字节)的小端序结构, int arr[]的单个字节看起来像这样(最低有效字节在下面的地址,所有的值都是hex):

 |01 00 00 00|02 00 00 00|03 00 00 00|04 00 00 00|05 00 00 00 
 char *ptr = (char *) arr; 

现在, ptr指向第一个字节 – 因为您已经转换为char* ,所以它被视为字符数组向前:

 |1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0 ^ +-- ptr 

然后, *(ptr+4)访问char数组的第五个元素并返回相应的char值:

 |1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5|0|0|0 ^ +-- *(ptr + 4) = 2 

因此, printf()打印2

在Big Endian系统中,每个int内的字节顺序相反,导致

 |0|0|0|1|0|0|0|2|0|0|0|3|0|0|0|4|0|0|0|5 ^ +-- *(ptr + 4) = 0 

这是因为char的大小是1, int的大小是4。 这意味着将4添加到ptr会使结果指向int数组中的第二个条目。

如果你在一个大的endian系统上编译,你将会打印33554432。

 int main(){ int arr[] = {1,2,3,4,5}; char *ptr = (char *) arr; printf("%d",*(ptr+4)); return 0; } 

每个arr大小都有sizeof(int)大小(在你的实现中可能是4)。

由于ptr是一个指向char的指针,因此指针运算会在&arr[0]之后4个字节ptr + 4个点,这可能是&arr[1]

在内存中,它看起来像这样:

 Address | 0 1 2 3 | 4 5 6 7 | ... Value | arr[0] | arr[1] | ... 

你所做的绝对不是在生产代码中推荐的,但是在学习过程中对于理解指针,表演等是绝对有用的,所以对于这个例子来说是很棒的。 所以,为什么你得到2.这是因为你的数组是一个整数,这取决于你的架构有不同的大小(在你的情况, sizeof(int)是4)。 您将ptr定义为一个char指针,char的大小为1个字节。 指针算术(这就是你写ptr+4时所做的)与指针所引用的对象的大小一致,在你的情况下用字符。 因此, ptr+4距离数组的开始4个字节,因此在你的int数组的第二个位置。 这就对了。 尝试ptr+5 ,你应该得到0。

在32位平台上, intchar四倍。 当你给ptr加4时,你把ptr指向 ptr(它本身就是一个内存位置)的大小增加4倍。 这恰好是int数组中第二个元素的地址。

在64位平台上, intchar 8倍, 和你的输出将是非常不同的。

长话短说,你的代码是不可移植的(也可以参考Joachim Pileborg的回答),但有趣的是取消。

由于你是int *转换为char *,ptr [0] = 1,ptr [4] = 2,ptr [8] = 3,ptr [12] = 4,ptr [16] = 5,其他都等于0 。ptr + 4指向ptr数组中的第四个元素。 所以结果是2。

 int main(){ int arr[] = {1,2,3,4,5}; char *ptr = (char *) arr; printf("%d",*(ptr+4)); return 0; } 

想象一下, arr存储在地址100 (完全哑地址)。 所以你有: arr[0]被存储在地址100处arr[1]被存储在地址104处(由于inttypes,存在+4) arr[2]被存储在地址108处arr[3]被存储在地址112处。等等

现在你正在做char *ptr = (char *) arr; ,所以ptr = 100(和arr )。 下一条语句很有趣,特别是printf的第二个参数: *(ptr+4) 。 请记住ptr = 100。所以ptr + 4 = 104,与arr[1]地址相同! 所以它会打印arr[1]的值,即2。