下面两行,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(&a+1);
printf("%d",*(ptr-1));
这会在屏幕上打印 5。而当使用 a 而不是 &a 时,
char a[5]={1,2,3,4,5};
char *ptr=(char *)(a+1);
printf("%d",*(ptr-1));
这会打印 1
a和&a都是数组的起始地址,为什么会这样呢
还有 字符 *ptr=&a+1;
显示警告。
最佳答案
数组不是指针!阅读section 6 of the comp.lang.c FAQ获取更多信息。
让我们先看看你的第二个案例,因为它看起来更“正常”和惯用。一行一行:
- 您声明一个包含 5 个
char
元素的数组a
。 - 数组的名称 (
a
) 在此上下文中衰减为指向其第一个元素的指针。您将1
添加到它并将结果分配给ptr
。ptr
指向2
。不需要强制转换,尽管你有一个。 - 您从
ptr
中减去1
,然后取消引用并打印 - 因此您得到1
。
现在,让我们逐行处理第一种情况:
- 您声明一个包含 5 个
char
元素的数组a
。 - 您获取
a
的地址,产生一个char (*)[5]
类型的指针。然后,您将1
添加到该指针 - 由于指针算法,该新指针将传递到内存中5
之后的字节。然后您进行类型转换(这次是必需的)并将此值分配给ptr
。 - 从
ptr
中减去1
,然后引用并打印。ptr
是一个char *
,所以这个减法只是将指针从“a
末尾后一位”向后移动一位以指向a
的最后一个元素。因此你得到了5
。
最后,char *ptr=&a+1;
给出警告的原因是因为 C 需要指针类型之间的转换才能进行显式转换。如前所述,&a
是char(*)[5]
类型,不是char *
,所以要将该值分配给 char *
变量,您将需要显式转换。
关于c - 数组a和&a的起始地址,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16312299/