-
外部變量
鎖定
- 中文名
- 外部變量
- 適用領域
- 數學、計算機
- 所屬學科
- 計算機科學
- 實 質
- 函數外部定義的全局變量
- 作用域
- 從變量的定義處開始
- 類 型
- 函數
外部變量定義
在B語言、C語言和一些其它派生的語言(如C++)中,外部變量即外部的變量。這並不是語言規範中直接明確的概念,因此含義可能有歧義。嚴格地,“外部”可以指變量名具有的外部鏈接(external linkage),據此外部變量指變量名具有外部鏈接的變量。其它理解導致外延與之具有一定差異,在下面的例子中註釋。
注意“變量”的概念在這些語言中本身即具有一些差異。ISO C中沒有作為名詞的“變量”(variable)這一術語的正式定義,通常即指對象,而ISO C++規定變量通過對象或不是非靜態數據成員的引用的聲明引入,其中“對象”的概念和ISO C的基本兼容。
[1]
外部變量extern聲明
extern可省略不寫。
本文件裏:在一個文件裏,有不止一個函數,外部變量在第一個函數後面定義。若用extern在第一個函數前聲明該變量則該變量可以在第一個函數中使用。
file1.c file2.c int i,j; //定義全局變量 extern int i,j; //外部變量説明, extern可以省略 char c; extern char c; void func() void func1() { { i = 100; printf(" i = %d, j = %d ", i, j); j = 10; } }
外部變量例子
下面的文件可以作為C或C++(源代碼確保符合ISO C11和ISO C++11)的源文件,分別作為一個翻譯單元,翻譯後鏈接為一個程序。
文件1:
int GlobalVariable; // 同一個翻譯單元中,在文件作用域(C)或全局命名空間作用域(C++)的首次聲明的變量名隱式具有外部鏈接 void SomeFunction(void); // 不是函數定義的函數聲明,因為明確指定了具體類型,在C語言中是函數原型 int main() { GlobalVariable = 1; SomeFunction(); }
文件2:
extern int GlobalVariable; // 通過關鍵字extern顯式指定被聲明的變量名具有外部鏈接 // static int GlobalVariable; // 若使用static關鍵字,可顯式指定被聲明的變量名具有內部鏈接,這樣就不會指稱翻譯單元中聲明的具有外部鏈接的對象,即使變量名相同 void SomeFunction(void) { // 函數定義 // int GlobalVariable; // 若在這裏聲明變量,則隱藏塊作用域外部的變量名,這個變量沒有鏈接,和塊作用域外部的變量名不同 // extern int GlobalVariable; // 若在這裏以extern聲明同名變量,則重複聲明之前的變量,鏈接取決於之前的聲明,可能是或者不是外部鏈接 ++GlobalVariable; }
在每個翻譯單元中,標識符都必須先被聲明。這個例子裏,變量 GlobalVariable 在文件1中被聲明,這個聲明同時是定義。為了在文件2中使同一個標識符指稱相同實體,它必須被聲明具有外部鏈接。
ISO C要求函數或對象的標識符若被使用則有且僅有一個外部定義,或未被使用時可以沒有定義或具有一個定義,否則行為未定義。通常除非使用擴展(例如弱符號),實現(鏈接器)一般會有檢查。
ISO C++規定合式(well-formed)必須在符合語法規則、可診斷語義規則的同時遵守One Definition Rule,其中多個翻譯單元內的同一個實體必須具有唯一定義,這包括具有外部鏈接的變量。不管有多少個翻譯單元,定義在整個程序中有且僅有一個。對於跨翻譯單元的情形,如果違反此規定,通常會產生鏈接錯誤。
除了外部鏈接,“外部”可能被理解為“在塊作用域外部”,見例子中SomeFunction函數定義中的註釋。這裏,“外部”變量不一定具有外部鏈接(比如,首次聲明時顯式使用了static關鍵字指定變量名具有內部鏈接,或者(C++)聲明在具有內部鏈接的無名命名空間(unnamed namespace)內部)。由於這些微妙的歧義,通常不使用這種理解。
由於C語言中外部鏈接的對象被習慣性誤稱為全局變量,“外部”還可能會被誤解為“全局”——嚴格地,這種理解的“外部”着眼於特定的源文件,指非當前翻譯單元。但是事實上C語言本身並沒有嚴格約定“全局”的含義。和C語言不同的是,C++存在嚴格意義上的全局變量,此處“全局”被正式定義為全局命名空間作用域。但是,這個概念的外延實際上和C++的“外部變量”不同:非全局命名作用域的變量的名稱可以具有外部鏈接,這不是全局變量;而全局命名空間作用域中也可以直接使用static聲明具有內部鏈接的全局變量。
此外,ISO C規定沒有初值符且沒有存儲類指示符(storage specifier)或static指定的對象聲明是tentative definition(ISO C++則明確禁止),和重複聲明一起可能顯著加劇上述理解的混亂。以下例子引用自ISO C11 6.9.2:
int i1 = 1; // definition, external linkagestatic int i2 = 2; // definition, internal linkageextern int i3 = 3; // definition, external linkage int i4; // tentative definition, external linkagestatic int i5; // tentative definition, internal linkage int i1; // valid tentative definition, refers to previous int i2; // 6.2.2 renders undefined, linkage disagreement int i3; // valid tentative definition, refers to previous int i4; // valid tentative definition, refers to previous int i5; // 6.2.2 renders undefined, linkage disagreementextern int i1; // refers to previous, whose linkage is externalextern int i2; // refers to previous, whose linkage is internalextern int i3; // refers to previous, whose linkage is externalextern int i4; // refers to previous, whose linkage is externalextern int i5; // refers to previous, whose linkage is internal
若外延限制為以上理解外延的交集,即文件作用域(C)/全局命名空間作用域(C++)中首次使用extern或沒有存儲類指示符的聲明引入的變量,則沒有歧義。絕大多數情況下,“外部變量”都屬於這個範疇。
外部變量static聲明
static聲明後該外部變量就只能在本文件中使用。
- 詞條統計
-
- 瀏覽次數:次
- 編輯次數:16次歷史版本
- 最近更新: Lemon西厢