通过内存组织方式可以看到,堆用来存放动态分配内存空间,而栈用来存放局部数据对象、函数的参数以及调用函数和被调用函数的联系,下面对二者进行详细的说明。
1.堆
在内存的全局存储空间中,用于程序动态分配和释放的内存块称为自由存储空间,通常也称之为堆。
在C程序中,是用malloc()和free()函数从堆中动态地分配和释放内存。
【例题】在堆中分配内存并释放
程序如下:
#include<studio.h>
int main()
{
int *plnt; /*定义整型指针*/
pInt=(int*)malloc(sizeof(int)); /*分配内存*/
*plnt=100; /*使用分配内存*/
printf("the number is: %d\n", pint); /*输出显示数值*/
return 0; /*释放内存*/
}
本程序中用malloc()函数分配一个整型变量的内存空间,在使用完该空间后,使用free()函数释放。
2.栈
在函数调用时,第一个进栈的是主函数中函数调用后的下一条指令(函数调用语句的下一条可执行语句)的地址,然后是函数的各个参数。在大多数的C编译器中,参数是由右往左入栈的,然后是函数中的局部变量。注意静态变量是不入栈的。
当本次函数调用结束后,局部变量先出栈,然后是参数,最后栈顶指针指向最开始存的地址,也就是主函数中的下一条指令,程序由该点继续运行。
栈是一个后进先出的压入弹出式的数据结构。在程序运行时,需要每次向栈中压入一个对象,然后栈指针向下移动一个位置。当系统从栈中弹出一个对象时,最晚进栈的对象将被弹出,然后栈指针向上移动一个位置。如果栈指针位于栈顶,则表示栈是空的;如果栈指针指向最下面的数据项的后一个位置,则表示栈为满的。其过程如图所示。
程序员通常会利用栈这种数据结构来处理那些最适用后进先出逻辑描述的编程问题。这里讨论的栈在程序中都会存在,它不需要程序员编写代码去维护,而是运行时由系统自动处理。所谓的运行时系统维护,实际上就是编译器所产生的程序代码。尽管在源代码中看不到它们,但程序员应该对此有所了解。这个特性和后进先出的特性是栈明显区别于堆的标志。
栈是如何工作的呢?例如,当一个函数A调用另一个函数B时,系统将会把函数A的所有实参和返回地址压入到栈中,栈指针将移动到合适的位置来容纳这些数据。最后进栈的是函数A的返回地址。
当函数B开始执行后,系统把函数B的自变量压入到栈中,并把栈指针再向下移,以保证有足够的空间来存储函数B声明的所有自变量。
当函数A的实参压入栈后,函数B就在栈中以自变量的形式建立了形参。函数B内部的其他自变量 也是存放在栈中的。由于这些进栈操作,栈指针已经压到所有局部变量之下。但是函数B记录了刚开始执行时的初始栈指针,以这个指针为参考,用正偏移量或负偏移量来访问栈中的变量。
当函数B正准备返回时,系统弹出栈中的所有自变量,这时栈指针移到了函数B刚开始执行时的位置。接着,函数B返回,系统从栈中弹出返回地址,函数A就可以继续执行了。
当函数A继续执行时,系统还能从栈中弹出调用者的实参,于是栈指针又回到了调用前的位置。
已有 22658 名学员学习以下课程通过考试
最需教育客户端 软件问题一手掌握
去 App Store 免费下载 iOS 客户端
点击加载更多评论>>