C 语言中的 extern 关键字

Jinku Hu 2023年10月12日
C 语言中的 extern 关键字

本文将演示关于如何在 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);
}
作者: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

DelftStack.com 创始人。Jinku 在机器人和汽车行业工作了8多年。他在自动测试、远程测试及从耐久性测试中创建报告时磨练了自己的编程技能。他拥有电气/电子工程背景,但他也扩展了自己的兴趣到嵌入式电子、嵌入式编程以及前端和后端编程。

LinkedIn Facebook