1 局部存储分配
基本概念
过程(函数、方法等):过程定义、过程调用、形参、实参
活动:过程的一次调用。
- 相关概念:活动的生存期
活动记录:每个活动的栈帧
名字(标识符):关键字、保留字等
变量:程序语言对机器内存单元的抽象
- 要素:名字、类型、字宽、地址、作用域、生存期
- 绝大多数的变量都有名字;没有名字的变量:临时变量、堆中变量
- 变量的地址 = 左值;变量的值 = 右值
- 程序中相同的变量在不同的时间可能关联到不同的地址
- 环境把名字映射到左值,而状态把左值映射到右值
- 赋值改变状态,但不改变环境
- 过程调用改变环境:不同的活动有不同的活动记录
- 如果环境将名字 x 映射到存储单元 s,则说 x 被绑定
绑定:实体和属性之间的关联
如:count = count + 2
count的类型在编译时绑定count的可能取值集合在语言设计时绑定count的值在运行时绑定+的含义在编译时确定操作数类型时绑定2的内部表示在语言设计时被绑定
静态绑定:运行前发生并且在程序执行期间保持不变
动态绑定:运行期间发生或者在程序执行期间改变
类型绑定:变量在被引用前必须绑定到数据类型
- 静态类型绑定 = 变量声明(显式声明、隐式声明/命名约定);方便但命名约定可能会损失可靠性
- 动态类型绑定:根据对变量的赋值推断变量的类型;灵活,但是代价高(动态类型检查、动态存储分配、解释执行等操作),难以在编译时检测类型错误
存储绑定
- 存储绑定:变量所绑定的内存单元的分配、回收(静态、栈、堆)
- 生存期(lifetime):变量绑定到某个存储单元的时间区间
控制绑定
- 作用域(scope):一个声明起作用的程序部分(局部变量、非局部变量)
- 命名空间(namespace):不同命名空间的同名符号含义互不相干
同名变量处理:如最近(小)嵌套作用域规则
并列程序块复用存储空间

全局变量处理:如 Python 中全局变量可以在函数中引用,但是只能对在函数中声明为 global 的全局变量赋值。
活动记录(activation record)的常见布局

局部数据的布局
- 字节是可编址内存的最小单位
- 变量所需的存储空间可以根据其类型而静态确定
- 一个过程所声明的局部变量,按这些变量声明时出现的次序,在局部数据域中依次分配空间
- 局部数据的地址可以用相对于活动记录中某个位置的地址来表示
- 数据对象的存储布局还需考虑对齐问题
对齐的实例
char: 1, long: 4, double: 8struct a { char c1; // 位置:0 long i; // 位置:4,5,6,7(位置1,2,3因对齐被浪费) char c2; // 位置:8 double f;// 位置:16~23(位置9~15因对齐被浪费) }; struct b { char c1; // 位置:0 char c2; // 位置:1 long i; // 位置:4~7 double f;// 位置:8~15 };
例题
一个 C 语言程序及其在 x86/Linux 操作系统上的编译结果如下。根据生成的汇编程序来解释程序中四个变量的存储分配、 生存期、作用域和置初值方式等方面的区别。
static long aa = 10;
short bb = 20;
extern int f();
int func() {
static long cc = 30;
short dd = 40;
cc = f(cc, dd); // 此处有变量提升
}
见 07-runtime-part1.pdf
本文阅读量