地址如何具有多个值?
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有两个值?
我将尝试借助图解释。
int i[5]={0,1,2,3,4,}; int *ip=&i[0];
在这段代码之后,我们有两个变量:5个int
的数组i
和指向数组i
第一个元素的指针ip
(即包含数组i
的第一个元素的地址)。 让我们看看这些变量是如何在内存中布局的(对于这个图,我假设int的大小为4,指针的大小为8,在你的系统上它可以是不同的,但对于你的问题,它现在无关紧要):
现在让我们看看printf参数并使用图解释它们:
-
*ip
– “取变量ip
的值 – 2358832 – 并将此值解释为地址,获取int
类型的值(因为ip
具有类型int *
),该值存储在此地址 – 0 ”; -
ip
– “获取变量ip
的值 – 2358832 ”; -
&ip
– “获取变量ip
的地址 – 2358824 ”; -
&i
– “获取变量i
的地址 – 2358832 ”; -
- 注1:变量通常占用多个存储单元,在这种情况下,“变量地址”表示该变量占用的第一个存储单元的地址=>变量
i
占用多个单元但具有地址“2358832” – 其第一个地址细胞;
- 注1:变量通常占用多个存储单元,在这种情况下,“变量地址”表示该变量占用的第一个存储单元的地址=>变量
-
- 注2:变量
ip
占用多个单元格(图中为8)
- 注2:变量
-
&i[0]
– “获取数组i
的第一个元素的地址 – 2358832 ”; -
i
– “获得变量i
的值 – ? ”。 这个很棘手。 当编译器请求获取“数组的值”时,编译器获取该数组的第一个元素的地址。 通常它被称为“数组衰减到指针” 。 所以在我们的例子中,i
=>&i[0]
=> 2358832 (见上文); -
i[0]
– “获取数组i
的第一个元素的值 – 0 ”; -
*(&i)
– 两个步骤: -
-
&i
=> 2358832 (见上文)。 请注意,此中间值(与任何其他值一样!)具有类型。 在这种情况下,type是int (*)[5]
– 指向数组的指针 。
-
-
-
*(&i)
– “获取存储在地址2358832的数组值”。 我们已经知道,“数组的值”表示该数组的第一个元素的地址 – 2358832 。
-
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)
相同,见上文。
令你困惑的是,之后
int i[5]={0,1,2,3,4,}; int *ip=&i[0];
“两个ip =&i = 2358832但是* ip = 0和*(&i)= 2358832。一个地址怎么能在2358832中有两个值?”。
两个表达式各自产生具有相同数值的地址。 如何通过打印解除引用这些相同地址的结果来certificate存储在同一地址的不同值?
如果你想到它,答案必须是ip vs&i的类型(以及printf的弱类型检查)。 它与C / C ++(hi Lundin)类型系统的一个微妙之处有关。 通常,一个数组“衰变”,正如语言所说,指向其第一个元素的指针。 这就是为什么你可以将i传递给一个带有指针(例如printf)的函数,或者向它添加1并获取下一个元素的地址,或者简单地将其取消引用它就像* i。
获取数组的地址是不会衰减的情况之一。 它保持arrays; &我有“指向数组的指针”类型,而不是“指向int的指针”。 数组与第一个元素共享其地址,因此数值相同。 但是编译器对指针的作用是不同的:
解除引用&i为您提供数组,与任何其他类型一样; 当你把它传递给像printf这样的函数时会发生什么? 最后,它衰减到指向其第一个元素的指针,该元素碰巧位于众所周知的地址2358832。
如果你想象一个结构来代替数组,它可能会变得更清楚; 这两者是相关的(结构也是一系列对象,只有不同类型)。 指向第一个struct成员的指针肯定与指向struct的指针有不同的含义,尽管它们肯定具有相同的数值。
或者采取以下一些(严格说明,未定义的行为)程序,该程序显示相同的地址可以携带“不同的值”,具体取决于您告诉编译器对数据执行的操作:
#include 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; }