返回首页
EN
H7 / SECURITY RESEARCH NOTES

第12章 存储类别、链接和内存管理

作用域

- 块作用域
块是一对用花括号括起来的代码区域,定义在块中的变量具有块作用域(block scope)。
块作用域变量的可见范围是从定义处到包含该定义的块的末尾。
注意,虽然函数的形参声明在函数的左花括号之前,但是它们也具有块作用域,属于函数体这个块。

- 函数作用域
跟goto标签相关,现在好像没讲。

- 函数原型作用域
函数作用域用于函数原型中的形参,其从形参定义处到函数原型结尾。

- 文件作用域
变量定义在函数的外面,具有文件作用域。其范围从定义处到该文件末尾处均可见。由于这样的变量可用于多个函数,也称为全局变量。

链接

# 3种链接属性
- 外部链接
具有文件作用域的变量可以是外部链接,外部链接的变量可以在多文件程序中使用。

- 内部链接
具有文件作用域的变量可以是内部链接,内部链接的变量只能在一个翻译单元中使用。
## 提问:这里的一个翻译单元是指一个文件吗?
## 答案:一个翻译单元指的是一个源代码文件和它包含的头文件
以 static 声明的文件作用域变量具有内部链接。

- 无链接
具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。


存储期

# 4种存储期
- 静态存储期
如果对象具有静态存储期,那么它在程序的执行期间一直存在。
所有的文件作用域变量具有静态存储期。

- 线程存储期
以关键字_Thread_local声明一个对象时,该对象具有线程存储期,每个线程都获得该变量的私有备份。

- 自动存储期
块作用域的变量通常都具有自动存储期。
当程序进入定义这些变量的块时,为这些变量分配内存;当退出这个块时,释放刚才为这些变量分配的内存。

- 动态分配存储期

存储类别

存储类别存储期作用域链接声明方式
自动自动块内
寄存器自动块内,使用关键字register
静态外部链接静态文件外部所有函数外
静态内部链接静态文件内部所有函数外,使用关键字static
静态无链接静态块内,使用关键字static
- 静态外部链接存储类别
静态外部链接类别也称外部存储类别(external storage class),属于该类别的变量称为外部变量(external variable)
把变量定义放在函数外面即创建了外部变量,如果要在函数中强调该函数使用了外部变量,可以用关键字 extern 再次声明。但如果外部变量位于另一个源代码文件的话,则必须用 extern 在该文件中声明该变量。

- 静态内部链接存储类别
属于该类别的变量称为内部链接的静态变量(static variable with internal linkage)

存储类别和函数

  • 函数也有存储类别,可以是外部函数(默认)或静态函数。外部函数可以被其他文件的函数访问,但是静态函数只能用于其定义所在的文件。
  • C99新增第三种类别--内联函数。
  • 使用static关键字声明定义在其他文件中的外部函数,为了表明当前文件中使用的函数在别处。

分配内存:malloc()free()函数

# 创建数组目前有三种方法:
1. 声明数组时,用常量表达式表示数组的维度,用数组名访问数组的元素,可以用静态内存或自动内存创建这种数组。
- int test_arr[10];

2.声明变长数组(C99新增特性)时,使用变量表达式表示数组的维度,具有这样特性的数组只能在自动内存中创建
- int i = 5;
- int test_arr[i];

3.声明一个指针,调用malloc()函数,将其返回值赋给指针,使用指针访问数组元素,该指针可以静态也可以自动。
- double * ptd;
- ptd = (double *) malloc(30 * sizeof(double));
  • free()函数和malloc()函数配合使用,free()函数的参数为之前malloc()返回的地址,该函数释放刚才malloc()分配的内存。

  • 使用malloc(),程序可以在运行时才确定数组大小。

  • ANSI之前,calloc()malloc()都返回指向char类型的指针,ANSI之后,返回指向void的指针。

ANSI C类型限定符

const类型限定符:
如果一个指针仅用于给函数访问值,应将其声明为一个指向const限定类型的指针。
volatile类型限定符;
restrict类型限定符;
_Atomic类型限定符;