我们常说的32位系统为每个进程分配4G虚拟内存空间(而MMU负责把这些个4G虚拟内存映射到实际内存条的物理内存),其实只有0~3G才是真正完全属于进程本身,是我们所说的用户区;3~4G这1G是所有进程间共享的,是我们所说的内核区,我们的程序是无法直接访问内核区的。
#include<stdio.h> int a; //未初始化全局区 .bss int b=1; //已初始化全局区 .data static int c=2; //已初始化全局区 .data const int d=3; //只读数据段,也叫文字常量区 ro.data, d的值不能被修改 int main(void) { int e=4; //栈区 static int f=5; //已初始化全局区 const int g=6; //栈区,不能通过变量名修改其值,但可通过其地址修改其值 int *p=malloc(sizeof(int)) //指针变量p在栈区,但其所指向的4字节空间在堆区 char *str="abcd"; //字符串“abcd”存在文字常量区,指针变量str在栈区,存的是“abcd”的起始地址 return 0; }
地方教材上常说:“全局变量在编译时分配空间,局部变量在运行时分配空间”,这在像vs这种集成式开发工具中,我们写个简单的程序,直接点个“运行”,编译、运行一步到位,很容易理解,但如果在linux上用vim写代码,用gcc编译生成a.out执行文件,再./a.out运行时,其实只剩下了“运行”这一步,那编译时分配又怎么解释呢?
其实编译时就只是确定了全局变量(静态局部变量也算)的虚拟地址,并且相关信息存在了可执行文件a.out中。我们再说一个进程(即正在执行的可执行文件)大概有4种状态:就绪(等待cpu)—>运行(占用cpu)—>挂起(等待cpu之外的资源,主动放弃cpu)—>终止 另外:初始态为进程准备阶段,常与就绪合并 ,就是在这个初始态阶段,做了很多准备工作,其中一项就是根据全局变量的虚拟地址映射物理地址为其分配空间,并初始化好。所以全局变量在程序进入main()函数之前,就已经在内存中存在了,而局部变量和堆区变量就只有程序执行到声明(或定义)它的那一条语句,才开始为其申请分配空间。
参考博客: