3:内存问题!静态内存、动态内存、栈、堆、内存、相互是怎么联系的? 问的是在计算里的内部操作是怎样进行的 因为我没学过任何计算机基础 内存是什么 也不知道,还有在某些情况下静态内存能否动态化。(大侠们 可以随便用程序举例)
在计算机眼里,一切都是线性化的。你看二进制数,01互相勾搭不断往前延伸,构成所有的概念。所谓内存,就是一条很长、很远的线性表,由01构成,每个点是0或1表示值,而这个点的坐标就是所谓的地址。无论是程序,还是数据(程序内使用的数据是程序占用的一部分),都排成一队放在这条绳的某个位置,这个位置的开始点,就是所谓的程序入口,就是main()的开始点。操作系统执行程序时,就是到这个地址查看数据,根据这些数据的指示进行不同的动作,比如在某个位置指示跳到另外一个位置执行那个位置的指令等等,这就是所谓的程序。
在我们写程序时,有些常数是已知的,已经写在程序代码中了,那么它就会成为程序的体积之一,放在程序的空间中,这是程序的静态数据区(编译器编译时会在程序占用空间中开辟专门存放这类数据的区域),有些是我们明确宣告尺寸的数据(比如int c[10]这样的数组,尺寸跟常数是一样事先可以确定的),也是放在静态内存区域。这是一种在编写程序时就已经确知占用空间的数据(包括程序代码本身),不是在运行时才临时计算出来的,就是“静态”概念。这种静态的东西,可以改变它的数据值,但无法再改变大小和位置了,但因为它有固定的地址和尺码,所以检索这样的数据就非常轻松(一般来说编译器会把这些数据紧密相邻地排在一起),只要内存空间够大,就尽量多使用这样的静态内存。
动态的概念,正与上面的静态相对立,那是一种事先无法确定下来的东西,必须临时计算。比如某个int类数组,它的元素个数没有在程序中确定下来,比方说要在scanf()中由人工输入某个数值,才说这个数组的元素是这个数。这样的数据,编译器是没有办法在编译程序时就落实它占用多少空间的,也就无法安排在静态数据区中,此时就会利用整个计算机空闲(指没有被任何程序使用)的内存作为这些数据的安身之处,此时,数据的地址不是由程序说了算,必须由操作系统分配给你,因为只有操作系统才知道整个计算机的所有程序对内存的占用情况,哪里有空闲的区域、是否足够容纳你申请的数据,都有它来确定,所以,这样的动态请求内存,未必总是可以成功,一旦操作系统发现没有办法满足你的要求,你的数据就完蛋了,没地方放了,程序也就走不下去了。也是这样的原因,程序向操作系统申请了空间,就必须在使用完后告诉操作系统回收,以便这些空间可以被别的程序使用(须知你现在这个空间也是别人释放了给你的),如果你总是申请不释放,越占越多,计算机再大的内存也未必能够满足你这种无限的胃口。这种由操作系统提供的内存空间,叫“堆”,malloc()函数就是申请堆空间的函数。
栈也是内存,只不过它的使用方式有点特殊。栈是编译器为程序预留的静态空间,但它是专门为程序的函数传递参数和返回值等使用的,故这个空间比较小(可以在编译参数中改变这个大小,好像是4K左右的样子)。函数在传递参数的时候,就向这个栈申请空间容纳参数的值,这就是所谓值传递参数复制值副本的说法,其原理跟堆是一样的,只不过此时管理这个空间的不是操作系统,而是程序自己。正因为这个空间本身很小,所以大尺寸的数据都尽量不用值传递(这就是默认数组传递总是传数组头指针的原因,只传地址,不需把整个数组复制到栈中,栈也容不下),递归过程很容易造成栈溢出,也是要谨慎使用的。
[
本帖最后由 TonyDeng 于 2011-8-12 17:11 编辑 ]