1 栈
存放的数据:
局部变量,函数参数,返回地址等。
默认初始值:
无默认初始值,为随机值。
分配者:
有编译器自动分配。
分配大小:
在程序开始后分配固定大小的栈空间,如果申请空间大于剩余栈空间,那么分配失败。
生长方向:
栈空间的生长方向是从高地址向低地址生长,即后申请的变量的地址小于先申请的变量的地址。
溢出:
如果新申请的变量小于剩余栈空间(因为分配是固定的栈大小),就会溢出。
特点:
系统自动分配,申请效率高,但程序员无法控制。
是否连续:
连续。
分配过程:
变量作用域:
局部作用域,它是自动对象(auto),在程序运行期间不是一直存在,而是只在函数执行期间存在,函数的一次调用执行结束后,变量被撤销,其所占用的内存也被收回。
2 堆
存放的数据:
由程序员动态(在代码中)申请的空间。
分配者:
由程序员申请,操作系统分配。
大小是否固定:
大小不是固定的,是由程序员决定每次申请空间的大小。
分配过程:
申请堆空间,堆在内存中呈现的方式类似于链表(记录空闲地址空间的链表),在链表上寻找第一个大于申请空间的节点分配给程序,将该节点从链表中删除。大多数系统中该块空间的首地址存放的是本次分配空间的大小。
在C中,可以使用malloc和calloc进行申请,两个函数都返回申请内存的首地址。两者的区别为:
- 两者参数个数不同:malloc只有一个参数,即你要分配的字节数,calloc有两个参数,一个为单元个数,另一个为每个单元大小
- 两者初始化不同:malloc不对分配的空间进行初始化,所以内存中是随机值。而calloc会将分配的空间初始化为0
溢出:
生长方向:
堆的生长方向为低地址向高地址生长。
回收:
程序员手动释放,如果程序结束时申请的空间还未释放,那么操作系统会自动将其回收。释放后,该块空间会被再次链接到链表上。在申请时,如果该节点还有剩余空间,也会将剩余空间连接到链表上。
默认初始值:
特点:
堆是由程序员主动申请,效率低,使用起来方便但是容易产生碎片。
是否连续:
不连续。
3 全局/静态存储区
存放的数据:
全局变量,静态全局变量,静态局部变量
由谁分配:
大小是否固定:
溢出:
生长方向:
回收:
程序结束之后操作系统自动将其释放。
默认初始值:
(记得时0,但是不确定)
特点:
在C中分为.bss段和.data段,未初始化的放在.bss段中, 初始化的放在.data中,在C++中不再区分。
是否连续:
分配过程:
变量作用域:
- 全局变量的作用域是全局作用域,全局变量只需在一个源文件中定义,就可以作用于所有的源文件。当然,其他不包含全局变量定义的源文件需要用
extern
关键字再次声明这个全局变量。 -
静态全局变量具有文件作用域。它与全局变量的区别在于如果程序包含多个文件的话,它作用于定义它的文件里,不能作用到其它文件里,即被 static 关键字修饰过的变量具有文件作用域。这样即使两个不同的源文件都定义了相同名字的静态全局变量,它们也是不同的变量。
-
静态局部变量具有局部作用域。它只被初始化一次,自从第一次被初始化直到程序运行结束都一直存在,它和全局变量的区别在于全局变量对所有的函数都是可见的,而静态局部变量只对定义自己的函数体始终可见。
注意,全局变量最好不要在头文件中定义,除非能保证该头文件只被包含一次。因为include头文件是将头文件代码插入到引用位置,所以全局变量定义到头文件会使得该变量被重复定义。
4 常量存储区
存放的数据:
存放的是常量,不允许修改
由谁分配:
大小是否固定:
溢出:
生长方向:
回收:
程序结束之后操作系统自动将其释放。
默认初始值:
特点:
是否连续:
分配过程:
变量作用域:
5 代码区
存放的数据:
存放代码,不允许修改,但可以执行。编译后的二进制文件存放在这里。
由谁分配:
大小是否固定:
溢出:
生长方向:
回收:
默认初始值:
特点:
是否连续:
分配过程:
变量作用域: