# include <stdio.h>
int main(void)
{
int i = 0;
printf("%d",&i);//这里出来的是 0 这个值所存在的位置。没错吧!
return 0;
}
上面代码中 出现的相应的字符 i 和 0 是不是都应该在内存中占有相应的位置?如果是,我打印出来的 &i 是指 0 这个值所占的内存位置,那 i 他本身 占的位置能找出来吗? 可能有人说胡扯, i 就是指那个 &i 这个地址里面存的那个值了,即 *&i == 0
,只是个变量了,代称了,他自己不存在位置了! 可是按道理来说 那些自己都应该在内存里面有相应的位置对不对?那 i 的位置能找出来吗?
我之所以冒出这个想法,是因为 这么个东西 比如 int* a = (int*)malloc[4];
有人说这句代码里面开辟了 8 个字节的内存空间。 他说原因是这样的 (int*)malloc[4]
;这个东西是指开辟了 4 个字节的动态内存空间对不对。但是这个函数返回值是 这开辟的4个字节的中的 第一个字节的位置 ,然后又把他赋给了 指针变量 a。 int* a
是声明了个指针变量,我们一般这么讲, 不管指针变量 指向的那个空间实际占几个字节(不管开辟的是4个字节,还8个字节),指针变量总是指向的是第一个字节位置(指针),所以 我们用 sizeof()来算指针变量的话 打印出来的 总是4(这个地方其实我也没完全搞懂)。所以上面那个代码 前后一共是开辟了 8个字节的空间。
等他说到这里,我这烂漫的想象力,就开始想象了。按到他的意思来说 int*a
开辟了一块内存空间,来存放后面的函数返回出来的第一个字节的指针位置! 我理解没错吧? 到这里我好像都有点忘了自己要问什么了。上面i是个整形变量,int*a
是个指针变量,都是变量后面这个自己开辟了一块内存空间,同理,i肯定也是存在一块内存空间里的是吧! 各位请回过头 再去想前面 关于 i 它本身存在的位置问题。其他不多说了。
线索 堆区 栈区 静态存储区
坐等大神来解答
-
栈上内存分配的情况
int i = 0; printf("%p\n", &i); // 这里的地址就是i本身的地址,0是存储在这个地址上的值, // 地址是额外编排的东西,就像你家的房子地址,最多 // 我拿一个号牌去记住他,但记不记这个是编译器的事情
上面这个情况
i
内存是在栈上分配的,存储空间本身存储的就是数据,栈空间是编译器来负责管理的,你只需要负责申请,编译器来负责分配释放,我们不需要记住这个地址,所以i
即变量本身,如果你需要地址,好,请使用&i
向编译器询问。 -
堆上内存分配的情况
int *a = (int*)malloc(4); // 注意不要写错了,不是 []
这种情况涉及到堆内存的分配,首先我们使用
malloc
系列的函数去分配内存的时候,会返回给我们一个地址,这是我们申请得到空间的首地址,而且重要的是我们在使用完的时候要手动使用free
释放内存(和上面栈上的内存不需要释放做对比)。
所以我们必须使用指针变量a
来记住这个地址,a
存储的是我们得到的地址(和上面的0
做下类比),还有就是a
本身是在栈上分配的,它亦有一个地址&a
(同上&i
)。
我们假设你printf输出的值为12345(0x3039),下面是一个演示图,在演示的过程中,我们假定编译器使用大端模式(即整数的高位存储在低字节):
int i = 0;
,那么在程序执行的时候,会在栈上分配一块内存区域,如上图所示是4个字节(一般编译器中整数都是四个字节),&i
取当前变量i
的存储位置第一个字节的地址,那么图中的情况的话,就是0x3039
了。
int i = 0;
中,i是变量,占用空间,0是立即数
,不占用空间,也就是说,0可以直接用于机器指令参数,无需做内存寻址。
因为你后面对 i 做取地址操作了,i 无法优化为 register int,所以 i 必须分配内存空间,分配到的位置就是你这个程序输出的结果。
我觉得你想问的是 &i 存在哪里?&i 不需要分配内存空间,可能会在寄存器里,也可能直接被编译器优化掉了。初始化用的右值 0 很可能也被优化为立即数了。但是标准没有规定放在哪里,编译器也可以选择放在别的地方,具体结果要看生成的汇编代码。
另外,思而不学则殆,不要想这么多没用的,先找本靠谱的课本,搞明白相关术语,我们才能知道你想问什么。