作用域
当变量被定义在程序的不同位置时,它的作用范围是不一样的,这个作用范围就是我们所说的作用域。
C语言编译器可以确认4种不同类型的作用域:
一代码块作用域
一文件作用域
一原型作用域
一函数作用域
1) 代码块作用域(block scope)
在代码块中定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志该代码块结束的右大括号)处。
尽管函数的形式参数不在大括号内定义,但其同样具有代码块作用域,隶属于包含函数体的代码块。
include<stdio.h>
int main(void)
{
int i = 100; //i1
{
int i = 110;//li
{
int i = 120;//i3
printf ( "i = %d\n", i);
}
//i =110
{
printf ( "i=%d\n", i);
int i = 130;
printf ( "i=%d\n", i);
}
printf ("i=%d \n", i);
}
printf("i= %d\n", i);
return 0;
}
2) 文件作用域(file scope)
任何在代码块之外声明的标识符都具有文件作用域,作用范围是从它们的声明位置开始,到文件的结尾处都是可以访问的。
另外,函数名也具有文件作用域,因为函数名本身也是在代码块之外。
#include <stdio.h>
void func(void);
int main(void)
{
extern int count;
func();
count++;
printf( "In main, count = %d \n", count);
return 0;
}
int count;
void func(void)
{
count++;
printf( "In func, count = %d \n", count);
}
3) 原型作用域(prototype scope)
原型作用域只适用于那些在函数原型中声明的参数名。
例如:
函数在声明的时候可以不写参数的名字(但参数类型是必须要写上的),其实函数原型的参数名还可以随便写一个名字,不必与形式参数相匹配(当然,这样做没有任何意义!)。
4) 函数作用域(function scope)
函数作用域只适用于goto语句的标签,作用将goto语句的标签暖制在同一个函数内部,以及防止出现重名标签。
- 定义和声明
当一个变量被定义的时候,编译器为变量申请内存空间并填充一些值。
当一个变量被声明的时候,编译器就知道该变量被定义在其他地方。
声明是通知编译器该变量名及相关的类型已存在,不需要再为此申请内存空间。
局部变量既是定义又是声明。
定义只能来一次,否则就叫做重复定义某个同名变量;而声明可以有很多次。
- 链接属性
external(外部的)
一多个文件中声明的同名标识符表示同一个实体
internal(内部的)
一单个文件中声明的同名标识符表示同一个实体
none(无)
一声明的同名标识符被当作独立不同的实体
只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用域的标识符都是none属性。
默认情况下,具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。
#include <stdio.h>
void a(void) ;
void b(void);
void c(void);
int count;
int main(void)
{
a();
b();
c();
b();
printf("小郭今天一共被抱了%d次\n", count);
return 0;
}
- 全局变量
extern int count;
void b (void)
{
count++;
}
使用static关键字可以使得原先拥有external属性的标识符变为internal属性。
这里有两点需要注意:
-使用static关键字修改链接属性,只对具有文件
作用域的标识符生效(对于拥有其他作用域的标识符是另一种功能)
一链接属性只能修改一次,也就是说一旦将标识符的链接属性变为internal,就无法变回external了