2011-08-30 103 views
4

非靜態聲明考慮這些例子:下面的靜態聲明

static int a; 
extern int a; //OK -- what linkage does the a have now? 

static int a; 
int a; //ERROR 

extern int a; 
static int a; //ERROR 

int a; 
static int a; //ERROR 

extern int a; 
int a; //OK as expected 

int a; 
extern int a; //OK as expected 

爲什麼它是在第一個例子確定,但不是在第二?

就文件範圍變量(全局範圍)而言,當沒有指定關鍵字時,它們具有外部鏈接和靜態持續時間。

謝謝

據我所知,連接和存儲持續時間功能是一個有點不同。

編輯: 我嘗試用gcc 4.5.2編譯-Wall -pedantic --std = C99

更多:http://c-faq.com/decl/static.jd.html你可以看到,第一個例子在那裏工作過,但第二次卻沒有。但是,我不明白是什麼讓他們如此不同。

+0

你可以更多地回答你的問題嗎?因爲在你第一次關心你評論確定,但是會產生一個錯誤,說「靜態聲明'a'遵循非靜態聲明」 – 2011-08-30 05:56:34

回答

3

答案第一個問題在C標準的§6.2.2中找到:

4爲了與存儲類說明extern 在範圍中聲明的標識符,其中的先前聲明如果先前的聲明指定了內部或外部鏈接,則後面聲明中標識符的 鏈接與先前聲明中指定的鏈接 相同。如果前面的聲明不可見,或者前面的聲明沒有指定鏈接,則 標識符具有外部鏈接。

所以a的鏈接是內部的。

關於第二個問題,緊隨其後段落的第二句是中肯的:

5如果一個標識符的某個函數的聲明沒有 存儲類說明,其聯動是完全一樣的決定如果它使用存儲類說明符extern聲明瞭 。如果一個對象的標識符的 聲明具有文件範圍,並且沒有 存儲類說明符,則其鏈接是外部的。

因爲a是一個對象,而非函數,聲明int a;沒有存儲類說明給出a外部連接。相同的部分於是具有這樣說的:

7如果,一個翻譯單元內,相同的標識符出現既 內外聯動,該行爲是未定義。

由於在第二個示例中,a與內部和外部鏈接一起顯示,因此會觸發此段落。一個(特別有用的)未定義行爲的表現是編譯器正在產生的錯誤。

您所有的例子可以通過這些規則來理解:

  1. int a;總是宣稱a外部鏈接;
  2. static int a;總是聲明a與內部聯繫;
  3. extern int a;聲明a與它已有的任何鏈接,或者如果它沒有外部鏈接;
  4. a在相同範圍內的兩個聲明有不同的聯繫,給出未定義的行爲。
+0

我想知道,外部繼承鏈接的基本原理是什麼?至於我,這隻會造成混亂。 – mindless

+0

「如果事先聲明指定內部或外部鏈接」。 這是否意味着它應該被明確指定,或者它也可以被隱決定就像是在你的第二個段落中提到: 「如果一個函數的標識符的聲明沒有存儲類說明,其聯動是完全一樣的決定如果它是用存儲類說明符extern聲明的「。 – mindless

+0

@mindless:我不認爲這很重要 - 那是'int a; extern int a;'case。 'extern int a''聲明有外部鏈接,因爲'int a;'聲明有外部鏈接,或者它有外部鏈接,因爲'int a;'聲明(直接)沒有指定鏈接 - 無論你使用什麼樣的解釋, 結果是一樣的。順便說一句,你引用第5段的第一句話是關於功能的。 – caf