指向字符串数组的指针 从int*转换后,我的char指针指向无效值




指向字符串数组的指针 (6)

我正在学习C编程语言,我刚开始用指针学习数组 。 我在这个问题上有问题,我希望输出必须是5但它是2 ,任何人都可以解释为什么?

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

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


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


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.(因为int类型是+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。


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

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

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

在内存中,它看起来像:

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

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

如果你在大端系统上编译它,你会打印33554432。


假设一个小的endian架构,其中int是32位(4字节), int arr[]的各个字节看起来像这样(较低地址的最低有效字节。所有十六进制值):

|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* ,它被视为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




pointers