变量作用域
1.作用域
作用域描述程序中可访问标识符的区域。一个C变量的作用域可以是块作用域,函数作用域,函数原型作用域或文件作用域。
- 代码块作用域
代码块是指一对花括号之间的代码,函数的形参虽然是在花括号之前定义,也属于代码作用域。
声明在内层块中的变量,其作用域仅局限在该声明所在的块:
int fun(int a){
int i;
for(i = 0; i < a; i++){
double q //q作用域的开始
...
} //q作用域结束
}
在这个例子中,q的作用域只在内层块,只有内层块中的代码才能访问q。
在C99中,把块的概念扩展到for循环,while循环,do-while循环和if语句所控制的代码当中。即使没有这些代码用花括号括起来,也算是块的一部分。
for(int i = 0; i < n; i++)// i的作用域仅限于for循环。一旦程序离开for循环,就不能再访问i
printf("%d", i);
- 函数原型作用域
用于函数原型中的形参名:
int fun(int a, int b);
函数原型作用域的范围是从形参的定义处到原型声明结束。编译器在处理函数原型中的形参时只关心它的类型,形参名则无关紧要。
- 文件作用域
变量的定义在所有函数的外面。具有文件作用域的变量,从它的定义处到该定义所在的文件的末尾均可见。
#include<stdio.h>
int a = 2;//a具有文件作用域
void fun(void){
...
}
int main(void){
...
}
这个例子中,a具有文件作用域,main()
和fun()
都可以使用它。由于这样的变量可以作用于多个函数,所以文件作用域变量也称作全局变量。
2.链接
C变量有三种链接属性:外部链接,内部链接或空链接。外部链接变量可以在多文件程序中使用,内部链接变量只能在一个翻译单元(一个源代码文件和它所包含的头文件)中使用。
- 空链接
具有块作用域,函数作用域或函数原型作用域的变量都是无链接作用域。这意味着他们是由其定义所在的代码块或函数原型所私有。
int a = 1; //文件作用域,外部链接
static int b = 2; //文件作用域,内部链接
int main(){
int a = 3; //空链接,仅为main函数私有
...
}
3.储存期
作用域和链接描述了标识符的可见性。储存期描述了通过这些标识符访问对象的生存期。
C对象有4种储存期: 静态储存期,线程储存期,自动储存期,动态分配储存期。
-
具有静态储存期的对象在程序执行期间一直存在。具有文件作用域的变量具有静态存储时期。对于文件储存变量来说,关键字static表明了它的连接属性而非储存期。
-
具有代码块作用域的变量一般情况下具有自动存储时期。在程序进入定义这些变量的代码块时,将为这些变量分配内存,当退出这个代码块时,分配的内存将被释放。
-
储存类别
储存类别 | 储存期 | 作用域 | 链接 | 声明方式 |
---|---|---|---|---|
自动 | 自动 | 块 | 空链接 | 块内 |
寄存器 | 自动 | 块 | 空链接 | 块内,使用关键字register |
静态外部链接 | 静态 | 文件 | 外部链接 | 所有函数外 |
静态内部链接 | 静态 | 文件 | 内部链接 | 所有函数外,使用关键字static |
静态空链接 | 静态 | 块 | 空连接 | 块内,使用关键字static |