int i[5]={0,1,2,3,4,};
int *ip=&i[0];
printf("%d,%d,%d,%d,%d,%d,%d,%d",*ip,ip,&ip,&i,&i[0],i,i[0],*(&i));
我在comp中得到的上面代码的输出是
0,2358832,2358824,2358832,2358832,2358832,0,2358832
观察ip=&i=2358832
但是*ip=0
和*(&i)=2358832
。
在这种情况下,一个地址如何解决2358832有两个值?
答案 0 :(得分:4)
int i[5]={0,1,2,3,4,};
int *ip=&i[0];
printf("%d,%d,%d,%d,%d,%d,%d,%d",*ip,ip,&ip,&i,&i[0],i,i[0],*(&i));
首先,使用%d
格式化地址是错误的。请使用%p
。你侥幸成功,因为你的地址恰好是4字节整数,与你的平台int
类型相同。
让我们一次完成这个:
*ip
与i[0]
相同。ip
包含数组的第一个元素的地址,它也是数组的地址,因为数组以其第一个元素开头。&ip
包含变量ip
。&i
包含数组的地址,与ip
中的地址相同,见上文。&i[0]
再次与ip
相同。i
是数组,它会衰减为指针,因此在将地址视为ip
,&i[0]
时具有相同的值。i[0]
,你知道那是什么。*(&i)
与i
相同,见上文。答案 1 :(得分:2)
我会尝试借助图解释。
int i[5]={0,1,2,3,4,};
int *ip=&i[0];
在此代码之后,我们有两个变量:5 i
s的数组int
和指向数组ip
的第一个元素的指针i
(即包含地址数组i
)的第一个元素。让我们看看这些变量是如何在内存中布局的(对于这个图,我假设int的大小为4,指针的大小为8,在你的系统上它可以是不同的,但对于你的问题,它现在并不重要):
现在让我们看看printf参数并使用图解释它们:
*ip
- “获取变量值ip
- 2358832 - 并将此值解释为地址,获取类型int
的值(因为ip
类型int *
)存储在此地址 - 0 “; ip
- “获取变量值ip
- 2358832 ”; &ip
- “获取变量地址ip
- 2358824 ”; &i
- “获取变量地址i
- 2358832 ”; i
占用许多单元格,但地址为“2358832” - 第一个单元格的地址; ip
也占用多个单元格(图中为8)&i[0]
- “获取数组i
的第一个元素的地址 - 2358832 ”; i
- “获取变量值i
- ?”。这个很棘手。当编译器请求获取“数组的值”时,编译器获取该数组的第一个元素的地址。通常它被称为“数组衰减到指针”。所以在我们的案例中i
=> &i[0]
=> 2358832 (见上文); i[0]
- “获取数组i
的第一个元素的值 - 0 ”; *(&i)
- 两个步骤:&i
=> 2358832 (见上文)。请注意,此中间值(与任何其他值一样!)具有类型。在这种情况下,类型是int (*)[5]
- 指向数组的指针。*(&i)
- “获取存储在地址 2358832 ”的数组值。我们已经知道,“数组的值”表示此数组的第一个元素的地址 - 2358832 。答案 2 :(得分:0)
在
之后,你会感到困惑int i[5]={0,1,2,3,4,};
int *ip=&i[0];
" ip =& i = 2358832但* ip = 0且*(& i)= 2358832。在这种情况下,一个地址如何解析2358832有两个值?"。
两个表达式各自产生一个具有相同数值的地址。如何通过打印取消引用这些相同地址的结果来证明相同地址中存储了不同的值?
如果你想到的话,答案必须是ip vs& i的类型(以及printf'弱类型检查)。它与C / C ++(hi Lundin)类型系统的一个细微之处有关。通常,数组"衰变",正如语言所说,指向其第一个元素的指针。这就是为什么你可以将i传递给一个带有指针(例如printf)的函数,或者为它添加1并获取下一个元素的地址,或者简单地将它取消引用它就像* i一样。
获取数组的地址是其不会衰减的情况之一。它保持阵列; & i的类型为"指向数组",而不是"指向int"的指针。该数组与其第一个元素共享其地址,因此数值相同。但是编译器对指针的作用是不同的:
解除引用& i为您提供数组,与任何其他类型一样;当你把它传递给像printf这样的函数时会发生什么?最后,它衰减到指向其第一个元素的指针,该元素碰巧位于众所周知的地址2358832处。
如果你想象一个结构代替数组,它可能会变得更清楚;这两者是相关的(结构也是一系列对象,只有不同类型)。指向第一个struct成员的指针肯定与指向struct的指针有不同的含义,尽管它们肯定具有相同的数值。
或者采取以下一些(严格说明,未定义的行为)程序,该程序显示相同的地址可以携带"不同的值",这取决于您告诉编译器对数据执行的操作:
#include<stdio.h>
int main()
{
unsigned int sixpointo = 1086324736;
float *fp = (float *)&sixpointo;
printf("&sixpointo: %p, fp: %p, sixpointo: %d, *fp: %f\n",
&sixpointo, fp, sixpointo, *fp);
return 0;
}