C - 作用域
C - 作用域
一个 C 变量的作用域可以是:
- 块作用域
- 函数作用域
- 函数原型作用域 或 文件作用域
作用域
描述程序中可访问标志符的区域。
块作用域
通常块
是一对花括号括起来的区域. 例如:
- 整个函数是一个块.
- 函数中的任意复合语句也是一个块.
定义在块中的变量具有块作用域(block scope)
, 块作用域变量的可见范围是从定义处到包含该定义的块的末尾. 另外, 虽然传入函数的形参声明在外部, 但是他们也具有作用域, 属于函数体这个块.
下面的代码中的变量 cleo 和 patrick 都具有块作用域:
double blocky(double cleo) {
double patrick = 0.0;
// ...
return patrick;
}
声明在内层块中的变量, 其作用域仅局限在该声明所在的块:
double blocky(double cleo) {
double patrick;
int i;
for ( i = 0 ; i < 10 ; i ++ ) {
// q 的作用域开始
double q = cleo * i;
patrick *= q;
} // q 的作用域结束
return patrick;
}
在该例中, q 的作用域仅限于内层块 for循环中, 只有内层块中的代码才能访问q.
以前, 具有块作用域的变量都必须声明在块的开头. C99 标准放宽了这一限制, 允许在块中的任意位置声明变量. 因此, 对于 for 的循环头, 现在可以这样写:
for ( int i = 0 ; i < 10 ; i ++ ) printf("A C99 feature: i = %d", i);
为适应这个新特性, C99 把块的概念扩展到包含 for循环, while循环, do while循环和 if 语句所控制的代码, 即使这些代码没有用花括号括起来, 也算是块的一部分. 所以, 上面的 for循环中的变量 i 被视作 for循环块的一部分, 他的作用域仅限于 for循环. 一旦离开 for循环, 就不能再访问 i.
函数作用域(function scope)
仅用于 goto 语句的标签. 这意味着即使一个标签出现在函数的内层块中, 他的作用域也延伸至整个函数. 如果两个块中出现相同的标签会很混乱, 标签的函数作用域防止了这样的事情发生.
函数原型作用域(function prototype scope)
用于函数原型中的形参名(变量名). 如下所示:
int mighty(int mouse, double large);
函数原型作用域的范围是从形参定义处到原型声明结束. 这意味着, 编译器在处理函数原型中的形参时, 只关心她的类型, 而形参名(如果有的话)通产无关紧要. 而且, 即使有形参名, 也不必与函数定义中的形参名相匹配. 只有在变长数组中, 形参名才有用:
void use_a_VLA(int n, int m, ar[n][m]);
方括号中必须使用在函数原型中已声明的名称.
定义在函数外面的变量, 具有文件作用域(file scope)
. 具有文件作用域的变量, 从他的定义处到该定义所在文件的末尾均可见.
#include <stdio.h>
int units = 0;
void critic(void);
int main(void) {
// ...
}
void critic(void) {
// ...
}
这里变量 units 具有文件作用域, main() 和 critic() 函数都可以使用它(更准确地说, units 具有外部链接文件作用域). 由于这样的变量可用于多个函数, 所以文件作用域变量也称为全局变量(global variable)
.