printf("code addr:%p\n", main);// 函数名代表的就是地址,通过打印 main 函数的地址来查看代码区的地址
const char *str = "Hello word";// 定义一个字符串常量
printf("read only string addr:%p\n", str);// 字符常量区的地址
printf("init global value addr:%p\n", &g_val_2);// 已初始化全局变量的地址
printf("uninit global value addr:%p\n", &g_val_1); // 未初始化全局变量的地址
char* men1 = (char*)malloc(100);
printf("heap addr-men1:%p\n", men1);
printf("stack addr-str:%p\n", &str);
static int a = 10;// 定义一个静态局部变量
printf("static a add:%p\n", &a);
return 0;
}
复制代码
小Tips:从打印结果中可以看出,静态变量的地址和全局变量的地址非常靠近。这是因为 static 修饰的局部变量,编译的时候已经被编译到全局数据区了。注意静态局部变量被编译到全局数据区仅仅是延长了该变量的生命周期,作用域并没有改变,照旧只能在 main 函数的作用域中使用该变量。 注意:本末节的所有代码验证都是基于 Linux 利用体系的,雷同的代码放在 Windows 利用体系中的 VS 下跑出来的结果可能会有所不同。 三、虚拟地址的引入
CPU 中有一个叫做 CR3 的寄存器(X86架构),该寄存器中生存的就是当前正在运行的进程的页表的地址,本质上属于当前进程的硬件上下文,当前进程被切换走了,是会把和该进程有关的所以硬件上下文数据带走的,固然就包括 CR3 寄存器中生存的该进程页表的首地址。该进程重新被 CPU 调理的时候,会把该这些硬件上下文数据重新加载到 CPU 里对应的寄存器中。CR3 寄存器中存的是物理地址。 4.3.2 页表是由页表项构成的