51

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

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

7 回答 7

81

假设 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
于 2013-07-02T11:15:21.330 回答
13

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

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

于 2013-07-02T11:09:17.860 回答
3
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,因此指针算术ptr + 44 个字节之后生成点&arr[0],这可能是&arr[1]

在内存中,它看起来像:

Address | 0 1 2 3 | 4 5 6 7 | ...
Value   |  arr[0] |  arr[1] | ...
于 2013-07-02T11:10:14.873 回答
2

在 32 位平台上,intchar. 当您将 4 添加到 时,您添加了 ptr 指向 ptrptr的大小的 4 倍(它本身就是一个内存位置)。这恰好是数组中第二个元素的地址。int

在 64 位平台上,大小int是 的8char;你的输出会非常不同。

长话短说,您的代码不可移植,(另请参阅 Joachim Pileborg 的回答 re endianness)但有趣的是取消选择。

于 2013-07-02T11:12:46.843 回答
2

在生产代码中绝对不建议您这样做,但对于在学习过程中理解指针、强制转换等绝对是非常有用的,因此您的示例非常棒。所以,为什么你得到 2。这是因为你的数组是一个整数数组,取决于你的架构,它有不同的大小(在你的情况下sizeof(int)是 4)。您定义ptr为 char 指针,char 的大小为 1 字节。指针算术(这就是您在编写时所做的ptr+4)适用于指针引用的对象的大小,在您的情况下适用于字符。因此ptr+4距离数组的开头有 4 个字节,因此位于数组的第二个位置int。这就对了。试试ptr+5,你应该得到 0。

于 2013-07-02T11:13:08.260 回答
1

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

于 2013-07-02T11:16:56.883 回答
1
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。(由于类型,有 +4 intarr[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。

于 2013-07-02T11:18:55.760 回答