2010-05-15 31 views
46

爲什麼extern int n在聲明n時(在不同的文件中)static int n不能編譯,但在聲明int n時有效? (這兩個聲明都在文件範圍內)。爲什麼extern不會鏈接到靜態變量?

基本上,爲什麼int n在文件範圍內與static int n不在同一範圍內?這只是與extern有關嗎?如果是這樣,我不知道extern呢?

回答

97

static的整個目的是聲明一個變量是私有的源文件,它在中聲明。因此,它正在盡其所能地阻止與外部的聯繫。

請記住,有文件範圍變量定義的四種口味:

  1. int blah = 0; - 嗒嗒在此文件中定義,並從其他文件訪問。其他文件中的定義是重複的,並且會導致錯誤。
  2. extern int blah; - 必須在其他地方定義並從此文件引用。
  3. int blah; - 這是FORTRAN COMMON的道德等價物。您可以在文件中包含任意數量的這些文件,並且這些文件均由鏈接器解析爲一個共享的int。 (*)
  4. static int blah;(可選帶初始值設定項) - 這是靜態的。這個文件是完全私有的。對於其他文件中的extern是不可見的,並且您可以擁有許多不同的文件,它們都聲明static TYPE blah;,它們都是不同的

對於觀衆中的純粹主義者:'file'= 編譯單元

請注意,靜態內部函數(不在文件範圍)的範圍更加緊密:如果兩個函數即使在同一個文件中聲明static int bleh = 0;,它們也是不相關的。 (*):對於那些你不熟悉的人:在通常的模式下,一個編譯單元必須定義一個全局變量,而其他編譯單元可以引用它。它「存在」在編譯單元中。在上面的情況(3)中,沒有文件(或所有文件)定義它。如果兩個文件說int blah = 0;,鏈接器將抱怨多個定義。如果兩個文件說int blah;鏈接器高興地創建一個單一的全球int並導致所有的代碼引用它。

+0

然後,根據存儲說明符調用'int n'(在文件範圍內)是什麼? – 2010-05-15 21:15:42

+0

@bmargulies:在檔案範圍,你的意思是?因爲在函數作用域中,靜態變量是在函數返回後保留其值的類型,而在類作用域中,靜態成員具有可用於所有對象的單個實例。 – mingos 2010-05-15 21:16:01

+0

編輯澄清,我相信。 – bmargulies 2010-05-15 21:17:45

5

在標準C中,有兩個在函數外聲明的變量的作用域。一個static變量只在聲明它的編譯單元(即文件)中可見,而非靜態變量在整個程序中可見。一個extern聲明說變量的位置還不知道,但會被鏈接器排序;它與非靜態變量兼容,但extern static只是瘋狂的談話!

當然,在實踐中,這些天還有其他可見性。特別是,現在在單個源文件和整個程序之間的範圍級別是一樣的;單個共享庫的級別非常有用(可通過GCC功能屬性等機制進行設置)。但這只是非靜態變量主題的一個變種; static保持與之前相同的解釋。

0

根據MSDN文檔:

When modifying a variable, the static keyword specifies that the variable has static duration (it is allocated when the program begins and deallocated when the program ends) and initializes it to 0 unless another value is specified. When modifying a variable or function at file scope, the static keyword specifies that the variable or function has internal linkage (its name is not visible from outside the file in which it is declared).

http://msdn.microsoft.com/en-us/library/s1sb61xd(v=vs.80).aspx:2013年6月

1

IV.C:2:1:錯誤:聲明指定多個存儲類 的extern靜態INT I; ^

這就是我們試圖通過外部靜態變量獲得的結果。聲明extern static int i; - 類似於聲明float int i; 你不能有float和int出現在同一個聲明中嗎?同樣,你不能在同一個聲明中使用extern和static。

相關問題