用C語言編寫程式的時候,我們經常會遇到這樣一種情況:希望在標頭檔中定義一個全域變數,然後包含到兩個不同的c檔案中,希望這個全域變數能在兩個檔案中共用。
舉例說明:專案檔夾project下有main.c、common.c和common.h三個檔案,其中common.h檔案分別#include在main.c和common.c檔案中。現在希望聲明一個字元型變數key,在main.c和common.c中公用。如所示:
有人想,既然是想兩個檔案都用,那就在common.h中聲明一個unsigned char key,然後由於內含項目關聯性,在main.c和common.c中都是可見的,所以就能共用了。
這種想法其實是很多初學者都會想到的,想起來確實有道理,但是實際寫出來,我們發現編譯的時候編譯器提示出錯,一般提示大概都類似於:Error:
L6200E: Symbol key multiply defined (by common.o and main.o). 也就是說編譯器認為我們重複定義了key這個變數。這是因為#include命令就是原封不同的把標頭檔中的內容搬到#include的位置,所以相當於main.c和common.c中都執行了一次unsigned
char key,而C語言中全域變數是項目內(或者叫工程內)可見的,這樣就造成了一個項目中兩個變數key,編譯器就認為是重複定義。
正確的解決辦法:使用extern關鍵字來聲明變數為外部變數。具體說就是在其中一個c檔案中定義一個全域變數key,然後在另一個要使用key這個變數的c檔案中使用extern關鍵字聲明一次,說明這個變數為外部變數,是在其他的c檔案中定義的全域變數。請注意我這裡的用詞:定義和聲明。例如在main.c檔案中定義變數key,在common.c檔案中聲明key變數為外部變數,這樣這兩個檔案中就能共用這個變數key了,如所示。
代碼如下(唯寫跟我們所說問題有關的部分):
(1)main.c檔案
#include "common.h"
unsigned char key;
(2)common.c檔案:
#include "common.h"
extern unsigned
char key;
很多人看了可能糊塗,這裡稍微說一下,其實就是變數定義和變數聲明的區別,變數定義使用“資料類型+變數名稱”的形式,編譯器需要給他分配記憶體單元的;而變數聲明使用“extern
變數類型+變數名稱”的形式,是告訴編譯器我這個變數將在其他外部c檔案中定義,我這裡只是在外部用它。編譯器就不給他分配記憶體空間,而等到真正遇到變數定義的時候再給他分配記憶體空間。
由於很多人從開始學C語言就一直把定義變數叫聲明變數,一開始就叫錯了,所以導致現在分不清定義和聲明的區別。要是還理解不了就想想函數的定義和聲明,函數定義是編寫函數功能實體,編譯器要編譯這個函數並且要分配記憶體空間,而函式宣告並不產生函數功能實體,只是告訴編譯器這是個函數,這個函數在後面將會定義實體,我這裡只是提前用,編譯器就會接著繼續往下編譯,如果子函數寫在main函數之後,那麼聲明是必須的,如果不聲明函數編譯器都不知道這是個函數,編譯就會報錯。
說了這麼多應該說明白了,如果還有問題可以參考譚浩強的那本C語言書,書中有詳細解釋和例子。
原文地址