签到

05月05日
尚未签到

共有回帖数 0

    李小主任

    等级:
    7.6  动态存储管理

    7.6.1  为什么需要动态存储管理
    程序中需要用变量(各种简单类型变量、数组变量等)保存被处理的数据和各种状态信息,变量在使用之前必须安排好存储:放在哪里、占据多少存储单元,等等,这个工作被称作存储分配。用机器语言写程序时,所有存储分配问题都需要人处理,这个工作琐碎繁杂、很容易出错。在用高级语言写程序时,人通常不需要考虑存储分配的细节,主要工作由编译程序在加工程序时自动完成。这也是用高级语言编程序效率较高的一个重要原因。

    C程序里的变量分为几种。外部变量、局部静态变量的存储问题在编译时确定,其存储空间的实际分配在程序开始执行前完成。程序执行中访问这些变量,就是直接访问与之对应的固定位置。对于局部自动变量,在执行进入变量定义所在的复合语句时为它们分配存储。应该看到,这种变量的大小也是静态确定的。例如,局部自动数组的元素个数必须用静态可求值的表达式描述。这样,一个函数在调用时所需的存储量(用于安放该函数里定义的所有自动变量)在编译时就完全确定了。函数定义里描述了所需要的自动变量和参数,定义了数组的规模,这些就决定了该函数在执行时实际需要的存储空间大小。

    以静态方式安排存储的好处主要是实现比较方便,效率高,程序执行中需要做的事情比较简单。但这种做法也形成了对写程序方式的一种限制,使某些问题在这个框架里不好解决。举个简单的例子:假设现在要写一个处理一组学生成绩数据的程序,被处理数据需要存储,因此应该定义一个数组。由于每次使用程序时要处理的成绩的项数可能不同,我们可能希望在程序启动后输入一个表示成绩项数的整数(或通过命令行参数提供一个整数,问题完全一样)。对于这个程序,应该怎样建立其内部的数据表示呢?

    问题在于写程序时怎样描述数组元素的个数。一种理想方式是采用下面的程序框架:

    int n;

    ...

    scanf("%d", &n);

    double scores[n];

    ... /* 读入成绩数据,然后进行处理 */

    但是这一做法行不通。这里存在两个问题:首先是变量定义不能出现在语句之后。这个问题好解决,可以引进一个复合语句,把scores的定义放在复合语句里。第二个问题更本质,在上面程序段里,描述数组scores大小的表达式是一个变量,它无法静态求出值。也就是说,这个数组大小不能静态确定,C语言不允许以这种方式定义数组。这个问题用至今讨论过的机制都无法很好解决。目前可能的解决方案有(一些可能性):

    1.         分析实际问题,定义适当大小的数组,无论每次实际需要处理多少数据都用这个数组。前面的许多程序采用了这种做法。如果前期分析正确,这样做一般是可行的。但如果某一次实际需要处理的数据很多,程序里定义数组不够大,这个程序就不能用了(当然,除非使用程序的人有源程序,而且知道如果修改程序,如何编译等等。在现实生活中,这种情况是例外)。

    2.         定义一个很大的数组,例如在所用的系统里能定义的最大数组。这样做的缺点是可能浪费大量空间(存储器是计算机系统里最重要的一种资源)。如果在一个复杂系统里,有这种情况的数组不止一个,那就没办法了。如果都定义得很大,系统可能根本无法容纳它们。而在实际计算中,并不是每个数组都真需要那么大的空间。

    上面只是一个说明情况的例子。一般情况是:许多运行中的存储需求在写程序时无法确定。通过定义变量的方式不能很好地解决这类问题。为此就需要一种机制,使我们能利用它写出一类程序,其中可以根据运行时的实际存储需求分配适当大小的存储区,以便存放到在运行中才能确定大小的数据组。C语言为此提供了动态存储管理系统。说是“动态”,因为其分配工作完全是在动态运行中确定的,与程序变量的性质完全不同。程序里可以根据需要,向动态存储管理系统申请任意大小的存储块。

    现在有了动态存储分配,可以要求系统分配一块存储,但是怎么能在程序里掌握和使用这种存储块呢?对于普通的变量,程序里通过变量名去使用它们。动态分配的存储块无法命名(命名是编程序时的手段,不是程序运行中可以使用的机制),因此需要另辟蹊径。一般的语言里都通过指针实现这种访问,用指针指向动态分配得到的存储块(把存储块的地址存入指针),而后通过对指针的间接操作,就可以去使用存储块了。引用动态分配的存储块是指针的最主要用途之一。

    楼主 2016-03-03 16:31 回复

共有回帖数 0
  • 回 帖
  • 表情 图片 视频
  • 发表

登录直线网账号

Copyright © 2010~2015 直线网 版权所有,All Rights Reserved.沪ICP备10039589号 意见反馈 | 关于直线 | 版权声明 | 会员须知