C 語言中的 extern 關鍵字

Jinku Hu 2021年2月7日
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);
}
Author: Jinku Hu
Jinku Hu avatar Jinku Hu avatar

Founder of DelftStack.com. Jinku has worked in the robotics and automotive industries for over 8 years. He sharpened his coding skills when he needed to do the automatic testing, data collection from remote servers and report creation from the endurance test. He is from an electrical/electronics engineering background but has expanded his interest to embedded electronics, embedded programming and front-/back-end programming.

LinkedIn