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);
}