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