「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战」
- 当变量被定义在程序的不同位置时,他的作用范围是不一样的,这个作用范围就是作用域。
4种不同类型的作用域
-
C语言编译器可以确认4种不同类型的作用域:
-
代码块作用域
- 代码块就是位于花括号之间的语句:如函数体、函数体内的复合语句
- 在代码块中定义的变量,具有代码块作用域。作用范围是从变量定义的位置开始,到标志该代码块结束的右大括号‘}’结束
- 尽管函数的形式参数不在大括号内定义,但其同样具有代码块作用域,隶属于包含函数体的代码块。
- 举例
- 结果
-
文件作用域
- 任何在代码块之外声明的标识符都具有文件作用域,作用范围是从它们的声明位置开始,到文件的结尾处都是可以访问的。
- 另外,函数名也具有文件作用域,因为函数名本身也是在代码块之外。
- 举例
- 结果
-
原型作用域
- 原型作用域只适用于那些在函数原型中声明的参数名。函数声明时可以不写参数的名字(但参数类型是必须要写上的),其实函数原型的参数名还可以随便写一个名字,不必与形式参数相匹配(当然,这样做没有任何意义)。
- 举例
-
函数作用域
- 函数作用域只适用于goto语句的标签,作用将goto语句的标签限制在同一个函数内部,以及防治出现重名标签。
-
定义和声明
-
定义和声明
- 当一个变量被定义的时候,编译器为变量申请内存空间并填充一些值。(即申请一个具体的坑存放数据)
- 当一个变量被声明的时候,编译器就知道该变量被定义在其他地方。(声明是告诉编译器这个变量定义过,找不到不要报错,接着往下找)
- 声明是通知编译器该变量名及相关的类型已存在,不需要再为此申请内存空间。
- 局部变量即是定义又是声明。
- 定义只能来一次,否则就叫做重复定义某个同名变量;而声明可以有很多次。
链接属性
-
链接属性
- 编译:将源代码生成机器代码(目标文件),后缀由c变为o
- 链接:将目标文件以及相关的库文件(如使用stdio.h中的printf函数,后缀lib)进行合并链接得到可执行程序,后缀exe
- external:多个文件中声明的通名标识符表示用一个实体
- internal:单个文件中声明的同名标识符表示同一个实体
- none:声明的同名标识符被当作独立而不同的实体
- 只有具备文件作用域的标识符才能拥有external或internal的链接属性,其他作用域的标识符都是none属性。(即函数名和全局变量才具有)
- 默认情况下,具有文件作用域的标识符拥有external属性。也就是说该标识符允许跨文件访问。对于external属性的标识符,无论在不同文件中声明多少次,表示的都是同一个实体。
-
举例(创建一个项目)
- 项目构造
- a.c、b.c和c.c(使用了extern关键字)
- main.c
- 项目构造
- 结果
-
使用static关键字可以使得原先拥有external属性的标识符变为internal属性。这里有两点需要注意:
- 使用static关键字修改链接属性,只对具体文件作用域的标识符生效(对于拥有其他作用域的标识符是另一种功能)
- 链接属性只能修改一次,也就是说一旦将标识符的链接属性变为internal,就无法变回external了。
- 举例(在上面代码的main函数内修改count,出现报错)