作用域就是关于变量在哪些上下文中是可见的。
这是几乎所有开发者定义变量的作用域。它包括其他语言可能称为“函数作用域”的内容,即在函数内部声明的变量。
基本规则是,如果你在一对大括号限定的代码块中声明了一个变量,那么该变量的作用域就是该代码块。
如果代码块内还有一个嵌套代码块,那么在内层代码块中声明的变量是该内层代码块的局部变量,外层代码块无法访问这些变量。
一旦变量的作用域结束,该变量就不再可被引用,你可以认为它的值已经进入了天空中的“位桶”。
嵌套作用域的示例如下:
#include <stdio.h>
int main(void)
{
int a = 12; // 对外层代码块局部,但对内层代码块可见
if (a == 12) {
int b = 99; // 对内层代码块局部,外层代码块不可见
printf("%d %d\\n", a, b); // 合法,输出 "12 99"
}
printf("%d\\n", a); // 合法,我们仍在变量 a 的作用域内
printf("%d\\n", b); // 非法,变量 b 已超出作用域
}
另一个有趣的事实是,你可以在代码块中的任意位置定义变量(在合理范围内)——它们的作用域仍然是该代码块,但在变量定义之前不能使用它们。
#include <stdio.h>
int main(void)
{
int i = 0;
printf("%d\\n", i); // 合法,输出 "0"
// printf("%d\\\\n", j); // 非法——不能在定义 j 之前使用 j
int j = 5;
printf("%d %d\\n", i, j); // 合法,输出 "0 5"
}
历史上,C语言要求所有变量必须在代码块中的任何代码之前定义,但在C99标准中,这条规则不再适用。
如果在内层作用域和外层作用域中有同名的变量,只要你在内层作用域中运行,内层作用域的变量就会优先使用。也就是说,它会在其生命周期内隐藏外层作用域中的那个变量。
代码示例:
#include <stdio.h>
int main(void)
{
int i = 10;
{
int i = 20;
printf("%d\\n", i); // 内层作用域 i,值为20(外层 i 被隐藏)
}
printf("%d\\n", i); // 外层作用域 i,值为10
}
你可能注意到在示例中,我只是在线7处放了一个代码块,而不是使用for或if语句来触发代码块!这是完全合法的。有时开发者会想把一堆局部变量放在一起,方便快速计算,也会这样写,但这种情况比较少见。
如果你在块之外定义一个变量,该变量具有文件作用域(file scope)。它在文件中其后出现的所有函数中都是可见的,并且它们之间共享。(例外是如果一个块定义了一个同名变量,它将隐藏文件作用域中的那个变量。)
这最接近你在其他语言中所认为的“全局”作用域。