翻译单元:源代码文件.c+其所有头文件.h
不细讲
块作用域函数作用域函数原型作用域文件作用域 (文件作用域变量可以是下文中的外部链接或内部链接)术语: 内部链接的文件作用域 — 简称为“文件作用域” 外部链接的文件作用域 — 简称为“全局作用域”、“程序作用域”
示例:
int glogal = 1; // 外部链接(全局作用域) static int file = 2; // 内部链接(文件作用域) int main{return 0;}标识符的四大存储期:
静态存储期自动存储期线程存储期动态分配存储期具有静态存储期的变量在程序执行期间将会一直存在
所有的文件作用域变量(内部链接和外部链接)都具有静态存储期
注意:
对于块作用域变量,static 是表明其存储期,而非链接属性(仍未无链接变量)对于文件作用域变量,内部链接变量的static 是表明其链接属性,而非存储期 //只不过static声明出来的内部链接变量是文件作用域变量,故自动具备了静态存储期自动存储期一般出现在块作用域中,程序进入块时,为具有自动存储期的变量分配内存,在程序推出块时,自动释放为其分配的内存
线程存储期用于并发程序设计中,具有线程存储期的变量,从声明到线程结束前一直存在。
使用malloc动态创建的变量,从malloc创建后到free释放前一直存在
//malloc与free #include<stdio.h> int main(){ double * ptr; ptr = (double *) malloc(30 * sizeof(double)); free(ptr); return 0; }malloc()参数为需要分配空间的字节数,free()参数为malloc返回的指针
malloc返回动态分配内存块的首字节地址,因此要通过一个指针来接收这个地址,分配空间失败时返回NULL空指针 为了提高程序的可读性,我们常常会使用类型转换,将malloc返回的地址转换为匹配的指针类型
free()函数只能够释放malloc()动态分配的空间,其他方式(如声明一个数组)分配的空间无法释放
因为标识符的储存方案由标识符的存储期和链接(作用域)决定,所以确定了存储方式也就确定了这个变量本身(我们一般根据变量的存储方式来命名变量)
五个常见储存方案
自动存储 - 自动变量寄存器存储 - 寄存器变量静态无链接存储 - 块作用域的静态变量静态外部链接存储 - 外部链接的静态变量静态内部链接存储 - 内部链接的静态变量 存储类别存储期作用域链接声明方式自动自动块无链接块内声明寄存器自动块无链接块内声明,使用关键字register静态无链接静态块无链接块内声明,使用关键字static静态内部链接静态文件内部链接所有函数外,且有关键字static静态外部链接静态文件外部链接所有函数外自动变量是声明在块中,在块作用域上,无链接,具有自动存储期的变量
为了强调变量该变量自动存储的类别,可以显示地使用关键字auto,确保变量为自动变量(确保自动存储类别)
自动变量不会自动初始化,只能显示地初始化(而静态变量自动初始化为0)
寄存器变量是通过register声明在块中,在块作用域上,无链接,具有自动存储期的变量
与普通的自动变量相比,一般来说 寄存器不储存在内存中而是直接储存在CPU的寄存器中(“编译器不一定允许储存”),因此访问和处理寄存器变量的速度更快。且因为是储存在寄存器上,故无法获得寄存器的储存地址,不允许指针操作
块作用域的静态变量是通过使用关键字static声明在块中,在块作用域上,无链接,具有静态存储期的变量
与普通的自动变量相比,块作用域的静态变量在所在函数块调用结束后并不会释放内存,而是一直保留在内存中,知道程序运行结束
代码示例:
// 块作用域的静态变量的特点 #include<stdio.h> void Print(){ int a = 0; static int b = 0; printf("局部变量a: %d, 块作用域的静态变量b: %d\n", a, b); } int main(){ for(int i = 0; i < 3; i++) Print(); return 0; }
内部链接的静态变量是通过关键字static声明在所有函数外,在文件作用域上,内部链接,具有静态存储期的变量
外部链接的静态变量是声明在所有函数外,在文件作用域上,外部链接,具有静态存储期的变量
extern"外部",意为 所声明变量的定义在外部,在别处
在使用外部链接和内部链接的静态变量时,为了防止同名变量的覆盖(防止编译器混淆声明与定义),我们按声明的位置把变量分为:
外部变量(external variable):,把变量的定义性声明放在了所有函数外面的变量内部变量:自动变量,寄存器变量,静态变量 #include<stdio.h> int num = 1; // 外部链接的静态变量 static char ch = 'a'; // 内部链接的静态变量 int main(){ extern int num; // 该语句为声明而非定义(再次声明了num外部链接的静态变量) extern char ch; /* int num; 该语句为定义,而非声明(定义了一个同名为num的局部变量) */ /* char ch; 该语句为定义,而非声明(定义了一个同名为ch的局部变量) */ return 0; }总结: 函数内使用extern,那么“外部”是相对于函数的,也就是指该文件的函数外 函数外使用extern,那么“外部”是相对于文件的,也就是指该文件外