什么是链接性
链接性 指的是标识符(如变量、函数)在多个翻译单元(通常是多个源文件)之间共享和可见的能力。链接性决定了标识符的作用范围,即它能在多大范围内被访问或引用
链接性
- 无链接性:标识符只能在局部作用域内使用,通常用于局部变量
- 内部链接性:标识符只能在定义它的文件内使用,使用 static 关键字声明
- 外部链接性:标识符可以在多个文件之间共享,默认情况下全局变量和函数具有外部链接性,使用 extern 关键字引用
什么是作用域
作用域是指一个变量或函数在程序中可以被访问的范围,可以简单理解为使用范围
链接性与作用域的关系
链接性决定了标识符在 多个翻译单元 之间的可见性,而作用域决定了标识符在 单个翻译单元 内的可见性
作用域
块作用域
块作用域是在代码块(如 {} 中)内部定义的变量,只在该块内可见
比如if语句,while语句等等,这里需要注意的是 switch-case 语句,它整个就是一个块作用域,如果重复定义一个变量会报错,示例如下
char c;
...
switch (c) { // 整个switch-case是一个块作用域
case 'a':
int count = 1; // 第一次定义count
break;
case 'b':
int count = 2; // 第二次定义count
break;
}
在这个示例中,每个case都是属于同一个作用域,所以count相当于在这个作用域内定义了多次,解决方法有两种,一个是在switch-case语句的外部定义,还有一种就是给case加上一个块作用域,独立于switch-case的这个大的作用域
// 法1
int count; // 在外部定义
switch (c) {
case 'a': ...
case 'b': ...
}
// 法2
switch (c) {
case 'a': {...} // 形成单独的作用域
case 'b': {...}
}
函数作用域
函数作用域是指所有在函数内定义的变量(包括局部变量和静态局部变量)的可见性和生命周期仅限于该函数
简单来说,就是你在函数内定义的变量就只能在该函数内使用,外面的访问不了
还有一个是,在函数内定义的标签(如 goto 标签)具有函数作用域,这意味着标签只在定义它的函数内有效,示例如下
#include <stdio.h>
void func() {
goto label; // label 只能在 func 函数内使用
label:
printf("This is a label.\n");
}
int main() {
func();
printf("%s", label); // 错误:label 在这里不可见
return 0;
}
文件作用域
在文件顶部定义的全局变量和函数在整个文件中可见。它们在文件外不可见,除非使用 extern 关键字, 默认为 外部链接
简单来说,就是定义在函数外部的变量,能被所有函数访问
外部作用域
使用extern关键字修饰的全局变量在多个文件中可见
需要注意的是,只能有一个定义,但可以有多个声明
通过这种方式,你可以在多个源文件中共享同一个全局变量
静态作用域
使用 static 关键字修饰的全局变量或函数只在定义它的文件内可见,全局变量 加上static修饰还是全局变量,static关键字只是改变了它的链接性,将外部链接改为内部链接
在函数内部使用static修饰局部变量,则该变量只会初始化一次,它的值会被保留下来
文件作用域对比静态作用域
他们的主要区别就在于链接性上面,当你在多个源文件中定义同名的变量、函数等,会发生命名冲突,这时候可以使用static限制这些全局变量的链接性
特征 | 文件作用域 (File Scope) | 静态作用域 (Static Scope) |
---|---|---|
可见性 | 在定义文件中可见,其他文件通过 extern 声明可访问 | 变量在其定义的块内可见,外部不可见 |
链接性 | 默认外部链接,使用 static 限制为文件内链接 | 静态作用域不涉及链接性 |
命名冲突 | 同名全局变量/函数在不同文件中会导致冲突 | 同名局部变量在同一函数内会导致冲突 |
解决方法 | 使用 static 或命名约定 | 使用不同名称 |
我的理解是,全局变量的链接性是外部链接,即在多个文件中是可见的,但这个可见性被加上了一个限制,那就是extern关键字,所有由于这种多个文件的伪可见,所以会有命名冲突(同名的函数也是),但是静态作用域是不涉及链接性的,根本没有这个问题
标签:case,函数,作用域,语言,全局变量,链接,定义 From: https://www.cnblogs.com/dylaris/p/18443142