一、作用域
1、代码快作用域(block scope):
在代码块的定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志该代码块结束的右大括号(})处。
尽管函数的形式参数不在大括号内定义,但其同样具有代码块作用域,隶属于包含函数体的代码块
#include<stdio.h>
int main(void)
{
int i = 100; //i1
{
int i = 110; //i2
{
int i = 120; //i3
printf("i=%d\n", i);
//嵌套内部的会覆盖外部的同名变量,所以这里的120替代了外面的,打印出120
}
{
int i = 130; //i4
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) //作用域从这里开始一直到return后面的括号;
{
extern int count;
func(); //先调用了func里的函数,有了1
count++; //再对其进行++,于是这里的count值为2
printf("In main:count =%d\n", count);
return 0;
}
int count;
void func() //作用域从这里开始,一直到大括号结束
{
count++;
printf("In func,count=%d\n", count); //这里只有一个,所以count的值为1
}
接下来的两种作用域使用较少,可做了解
3、原型作用域(prototype scope):
只适用于那些函数原型中声明的参数名。函数在声明的时候可以不写参数的名字(但参数类型是必须要写上的),
其实函数原型的参数名还可以随便写一个名字,不必与形式参数相匹配(当然这么做没有任何意义)实际上很少用到
eg: void func(int a,int b,int c);
void func(int d,int e,int f)
{
......
}
4、 函数作用域(function scope)
只适用于goto语句的标签,作用将goto语句的标签限制在同一个函数内部,以防出现重名标签
二、定义与声明
定义:当一个变量被定义的时候,编译器为变量申请内存空间并填充一些值
声明:当一个变量被声明的时候,编译器就知道该变量被定义在其他地方。声明是通知编译器该变量名及相关的类型已存在,不需要再为此申请内存空间
局部变量即是定义又是声明。
定义只能来一次,否则就叫重复定义某个同名变量;而声明可以有很多次
三、链接属性:有以下三种属性
1、external(外部的)---多个文件中声明的同名标识符表示同一个实体
2、internal(内部的)---单个文件中声明的同名标识符表示同一个实体
3、 none(无) ---声明的同名标识符被当做不同的实体
只有具备文件作用域的标识符才能拥有exteral或internal的链接属性,其他作用域的标识符都是none属性。
默认情况下,具备文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。
需要注意的是:使用static关键字可以使得原先拥有的external属性的标识符改为internal属性,这里有两点注意:
1、使用static关键字修改链接属性,只对具有文件作用域的标识符生效(对于拥有其他作用域的标识符是另一种功能)
2、链接属性只能修改一次,也就是说一旦将标识符的链接属性变为internal,就无法变回external了