如果一个变量在程序的某个部分被声明了,那么它必然有自己的作用域,不然整个程序就会乱套。作用域最明显的作用有两个:1.限制函数或者程序在变量的作用域外,通过变量名对其访问它,因为这些变量在作用域就失去功效;2.在这个变量的作用域外可以声明与其同名的变量。
那么C规定了4种作用域,分别是:文件作用域,函数作用域,代码块作用域,和原形作用域。
例1:
int a;//a,b具有文件作用域
int b;
int test(int g);//函数原形声明,g变量具有原形作用域
int test(int b){//函数定义
int c;
int d;
{
int d;//与外层作用域的变量同名
int f;
}
{
int f;//与上一个代码块中的变量同名
}
return 0;
}
代码块作用域
代码块就是一对花括号包起来的代码,在其中声明的变量它的作用域自然就属于代码块作用域,例如例1中的c,d,f。函数的形参天生具有函数中最外层的代码块作用域。例如例1中,b作为test函数的形式参数,它具有与c以及第一个d相同的代码块作用域,也就是函数test最外层的代码块作用域。位于代码块内部的变量,其代码块作用域的范围是从其声明开始,到代码块结束。
如果内层代码块的变量与外层代码块的变量同名的话,在内层代码块的那个变量将隐藏外层的代码块的那个变量,也就是在内层代码块中无法通过变量名来访问外层的代码块的同名的变量,例如,例一种第二个d将在其代码块作用域中覆盖第一个d,直到其代码块结束。
上面提到同名变量所处的代码块涉及到了嵌套,但当两个变量所处代码块不嵌套时,情况是另外一种,例1中,存在两个f,而两个f位于相互不嵌套的两个代码块,而两个代码块中的变量不可能同时存在,所以很多编译器会对这种情况进行优化,他们会为f分配同一块内存,这种优化不会带来任何危害,因为两个不嵌套的代码在任何时刻最多只有一个处于活动状态。
文件作用域
位于任意代码块外部的声明都具有文件作用域,他们的范围是从声明开始到文件结束。而函数的声明天生具有文件作用域。需要提醒的是,头文件里面的声明 的文件作用域不是到头文件的结尾就结束了,而是到通过#include加入此头文件的文件的结尾,因为#include命令就像将头文件的声明写入那些文件一样。
原形作用域
首先强调一点,此作用域只适用于函数声明中的参数,而函数定义中的参数具有代码块作用域。例如,例1中的g,在函数声明时,参数名不是必须的,只需说明参数类型即可,而且在函数声明以及定义中,参数名可以不保持一致。可以这么说,原形作用域的作用,就是在函数声明中,如果出现多个参数名,那么这些参数名不能一样。
函数作用域
函数作用域适用于语句标签,语句标签用于goto语句。也就是goto的语句标签要保持唯一。例如goto a,这时,代码里不能有多个a:来指定跳转的地方。