变量的作用域
作用域(scope)指的是变量生效的范围。C 语言的变量作用域主要有两种:文件作用域(file scope)和块作用域(block scope)。
文件作用域(file scope)指的是,在源码文件顶层声明的变量,从声明的位置到文件结束都有效。
int x = 1;
int main(void) {
printf("%i\n", x);
}
上面示例中,变量x
是在文件顶层声明的,从声明位置开始的整个当前文件都是它的作用域,可以在这个范围的任何地方读取这个变量,比如函数main()
内部就可以读取这个变量。
块作用域(block scope)指的是由大括号({}
)组成的代码块,它形成一个单独的作用域。凡是在块作用域里面声明的变量,只在当前代码块有效,代码块外部不可见。
int a = 12;
if (a == 12) {
int b = 99;
printf("%d %d\n", a, b); // 12 99
}
printf("%d\n", a); // 12
printf("%d\n", b); // 出错
上面例子中,变量b
是在if
代码块里面声明的,所以对于大括号外面的代码,这个变量是不存在的。
代码块可以嵌套,即代码块内部还有代码块,这时就形成了多层的块作用域。它的规则是:内层代码块可以使用外层声明的变量,但外层不可以使用内层声明的变量。如果内层的变量与外层同名,那么会在当前作用域覆盖外层变量。
{
int i = 10;
{
int i = 20;
printf("%d\n", i); // 20
}
printf("%d\n", i); // 10
}
上面示例中,内层和外层都有一个变量i
,每个作用域都会优先使用当前作用域声明的i
。
最常见的块作用域就是函数,函数内部声明的变量,对于函数外部是不可见的。for
循环也是一个块作用域,循环变量只对循环体内部可见,外部是不可见的。
for (int i = 0; i < 10; i++)
printf("%d\n", i);
printf("%d\n", i); // 出错
上面示例中,for
循环省略了大括号,但依然是一个块作用域,在外部读取循环变量i
,编译器就会报错。