系统内存布局
指针是C语言中的精华,也是C语言程序的重点和难点,在C语言编写的程序中,会大量使用到指针。因此,掌握C语言的指针,是非常重要的。懂了指针,就懂了C语言的大部分内容。
要理解指针,需要先理解下系统的内存布局和变量的内存地址,因为指针和内存地址是息息相关的。
以x86为例,x86支持32位寻址,因此可以支持最大232=4GB的虚拟内存空间(也可以通过PAE技术增加到36位寻址,因此可以将寻址空间扩大到64GB)。如图所示,在
X64(AMD64)的内存布局与X86的内存布局类似,不同的地方在于各自空间的范围和大小不同,同时X64下还存在着一些空洞(hole),如图所示。在X64内存理论上支持最大264的寻址空间,但实际上这个空间太大了,目前根本用不完,因此实际上的X64系统一般都只支持到40多位(比如Windows支持44位最大寻址空间为16TB,Linux 支持48位最大寻址空间256TB等),支持的空间达到了TB级别。但是,无论是在内核空间还是在应用层空间,这些上TB的空间并不都是可用的,存在着所谓的空洞。
X64与x86系统内存布局
当程序加载入内存后,程序在内存中可以分为若干个区,这些区包括:静态区(.data,.rdata,.bss段等),代码区(.text),堆区,栈区等。
.text 代码段,这个存放代码的,用汇编角度来看就是指令。
.rdata 只读数据段,存放常量,字符常量,const常量。
.data 数据段,存放已经初始化好的全局变量和静态变量。
.bss 存放未初始化的全局变量和静态变量。
.rdata,.data,.bss都是存放的数据。除了.bss段,.rdata,.data段的值都是在编译的时候就确定了,并且将其编译进了可执行文件,经过反汇编都能找得到。bss段是在代码运行的时候手动编写汇编代码将其初始化为0的(这就是未初始化的全局和静态变量默认值为0的根源)
.stack:栈区,存放局部变量等。如下图所示,栈区存放这函数调用过程中的形参,返回地址以及局部变量等(将在函数一章讲调用约定的时候具体介绍栈上的数据)。