## 栈与堆
如果我说 C 语言是一种部分支持垃圾内存回收的语言……你可能会认为我脑子坏掉了。事实上,C 语言中的所有的局部变量包括指针超出作用域时,它们所占据的存储空间都会被『回收』。这算不算内存垃圾回收?
从 C 程序的角度来看,内存并非一个以字节为单位的一个很大但是又经常不够用的空间,不是一个,而是两个。其中一个空间叫栈,另一个空间叫堆。可被 C 程序『回收』存储空间是栈空间。也就是说,在一个函数中,所有的局部变量所占据的存储空间属于栈空间。可能再说的学术一点,就是所有的左值都在栈空间(我不确定这样说到底是不是正确)。
当一个函数运行结束,它所占据的栈空间就不再属于它了,而是将会被一个新的待运行的函数占据。所以,从本质上说,C 程序对栈空间的回收都不屑一顾,因为它根本不回收,而是旧的数据会被新的数据覆盖。
堆空间,我们在程序里无法直接访问,只能借助指针。因为堆空间的内存地址可被指针引用。例如,当使用 `malloc` 分配空间时,所分配空间的基地址总是保存在一个位于栈空间的指针中的。
栈空间通常远远小于堆空间,即便如此也几乎不会出现某个函数会耗尽栈空间的现象。如果这种现象出现了,那只能证明造出这种现象的程序猿应该继续学习 C 语言了。栈空间被耗尽,往往是因为有些程序本来是写成递归,但可能是代码写错了,导致递而不归;还有一种可能是递归层次太深,这时可以想办法在堆空间中模拟一个栈来解决。还有一种情况就是在函数中定义了很大的数组,导致栈空间放不下……这种情况总是可以靠分配堆空间来解决。