C 知识量:16 - 74 - 317
作用域用于描述程序可访问标识符的区域。一个C变量的作用域可以是块作用域、函数作用域、函数原型作用域或文件作用域。
1、块作用域。
块是用一对花括号括起来的代码区域。定义在块中的变量具有块作用域,其变量的可见范围是从定义处到包含该定义的块的末尾。
此外,函数的形参虽然声明在函数左花括号之前,但它也具有块作用域,属于函数体这个块。
注意:声明在内层块中的变量,其作用域仅局限于该声明所在的块。例如:
void add(int a) { for (int i = 1; i <= a; i++) { int b = 0; b += i; } }
在以上代码中,变量a的块作用域从函数add的左花括号到右花括号。而变量i和变量b的块作用域仅限于for循环体内,一旦程序离开for循环,i和b就不能访问。
2、函数作用域。
函数作用域仅用于goto语句的标签。这意味着即使一个标签首次出现在函数的内层块中,它的作用域也延伸到整个函数。
3、函数原型作用域。
函数原型作用域用于函数原型中的形参名。函数原型作用域的范围是从形参定义处到原型声明结束。因此,编译器在处理函数原型中的形参时,只关心它的类型,而形参名通常不重要,即使没有形参名称也没关系,也不要求与函数定义中的形参同名。例如:
void add(int abc);
以上代码中的形参abc,其作用域范围仅限于该声明,其名称与函数定义中也不一致。
需要注意:在变长数组中,形参名是重要的,[]中的变量名称需要与已定义的一致。
4、文件作用域。
定义在函数外面的变量具有文件作用域。其范围从它定义处到该定义所在文件的末尾。例如:
#include <stdio.h> int a = 5; int main(void) { for (int i = 1; i <= a; i++) { int b = 0; b += i; } system("pause"); return 0; }
以上代码中,变量a就具有文件作用域,在整个文件中都有效。这样的变量又称全局变量。
C的变量有3种链接属性,分别是:
外部链接
内部链接
无链接
具有块作用域、函数作用域或函数原型作用域的变量都是无链接变量。这些变量属于定义它们的块、函数或原型私有。
具有文件作用域的变量可以是外部链接,也可以是内部链接。外部链接变量可以在多文件程序中使用,而内部链接变量只能在一个翻译单元中使用。翻译单元即一个源代码文件和它所包含的头文件。
可以通过查看定义中是否使用了存储类别说明符static来辨别文件作用域变量是内部链接还是外部链接,例如:
#include <stdio.h> int a = 100; //文件作用域,外部链接 static int b = 200; //文件作用域,内部链接 int main(void) { ... }
以上代码中,变量a可以被该文件和同一程序的其他文件使用,而变量b属于该文件私有,该文件中的任意函数都可以使用它。
作用域和链接描述了标识符的可见性。存储期用于描述通过这些标识符访问的对象的生存期。
C语言有4种存储期:
静态存储期
线程存储期
自动存储期
动态分配存储期
1、静态存储期。
如果对象具有静态存储期,那么它在程序执行期间一直存在。文件作用域变量具有静态存储期。
2、线程存储期。
线程存储期用于并发程序设计,具有线程存储期的对象,从被声明到线程结束一直存在。
3、自动存储期。
块作用域的变量通常具有自动存储期。当程序进入定义这些变量的块时,为这些变量分配内存;当程序退出这个块时,释放这些变量占用的内存。
对于变长数组来说有些不同,它的存储期从声明处到块的末尾,而不是从块的开始处到块的末尾。
块作用域的变量也可以具有静态存储期,创建这样的变量需要在声明前加上关键字static。
主要的存储类别如下表:
存储类别 | 存储期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 无 | 块内 |
寄存器 | 自动 | 块 | 无 | 块内,使用关键字register |
静态外部链接 | 静态 | 文件 | 外部 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部 | 所有函数外,使用关键字static |
静态无链接 | 静态 | 块 | 无 | 块内,使用关键字static |
Copyright © 2017-Now pnotes.cn. All Rights Reserved.
编程学习笔记 保留所有权利
MARK:3.0.0.20240214.P35
From 2017.2.6