C 语言中的 extern 关键字
Jinku Hu
2023年10月12日
本文将演示关于如何在 C 语言中使用 extern
关键字的多种方法。
C 语言中使用 extern
关键字来声明一个在其他文件中定义的变量
一般来说,C 语言的变量有 3 种不同的链接类型:外部链接、内部链接或无链接。如果一个变量定义在块或函数范围内,就认为它没有链接。一个具有文件作用域的变量可以有内部链接或外部链接。也就是说,如果一个全局变量用 static
限定符声明,它就具有内部链接,意味着该变量可以在一个源文件(更准确的说是翻译单元)中使用。没有 static
限定符的全局变量被认为具有外部链接,可以在不同的源文件中使用。如果要使用在其他源文件中定义的全局变量,应该使用关键字 extern
来声明。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
extern int counter;
int main(void) {
printf("counter: ");
for (int i = 0; i < COUNT; ++i) {
counter += 1;
printf("%d, ", counter);
}
printf("\b\b \n");
exit(EXIT_SUCCESS);
}
输出:
counter: 1, 2, 3, 4, 5, 6, 7, 8, 9, 10
extern
限定变量通常定义在不同文件的某个地方。不过,从技术上讲,我们还是可以在同一个文件中使用 extern
关键字来声明全局变量,如下例所示。这种类型的声明本质上是多余的,因为编译器会自动使变量名在同一文件范围内的任何地方可见。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
int counter2 = 0;
int main(void) {
extern int counter2; // redundant
counter2 += 10;
printf("%d\n", counter2);
exit(EXIT_SUCCESS);
}
不过要注意,extern
声明的变量不应该被初始化,因为如果我们在一个源文件中定义 const char*
全局变量,然后用一些字符串文字值初始化它,会导致编译器警告。在不同的源文件中声明同一个没有 const
修饰符的变量,在编译时不会出现警告,而且会删除对象的 const 性。因此,如果用户试图修改只读字符串 tmp
,编译器不会抛出错误,但程序会遇到分段故障。
#include <stdio.h>
#include <stdlib.h>
#ifndef COUNT
#define COUNT 10
#endif
extern int counter;
// extern int counter = 3; // erroreous
extern char *tmp; // erroreous
int counter2 = 0;
int main(void) {
printf("counter: ");
for (int i = 0; i < COUNT; ++i) {
counter += 1;
printf("%d, ", counter);
}
printf("\b\b \n");
tmp[0] = 'S'; // segmentation fault
printf("%s", tmp);
exit(EXIT_SUCCESS);
}