2010-02-27 61 views
1

AFAIK,extern關鍵字應該用於聲明,並且沒有值可以與使用extern關鍵字聲明的變量關聯。但假設我寫了一個像與extern關鍵字使用有關的疑問

extern int i = 10; 

該編譯器應該標記一個錯誤的相同?我看到一些編譯器容忍並忽略這一點?這是爲什麼? 'C'標準對此有何評論?

編輯:@All,感謝您的答案。儘管如此,我仍然有疑問。假設我有這個變量的定義,而沒有在另一個文件中的外部鏈接說a.c,我在b.c中添加了這個語句。編譯器不會標記錯誤還是可以的嗎?它是否重新定義?

+0

不,因爲這實際上是一個定義而不是一個聲明。 – Clifford 2010-02-27 23:50:04

+0

LLVM會引發一個警告:「extern變量有一個初始化程序」 – Binarian 2013-10-05 14:23:17

回答

6

這是有效的語法,在C99標準中甚至有一個基本相同的例子。 (請參閱第6.9.2-4節。)

的確,這些示例不是規範性的,但我相信它的目的是成爲合法的語法。編譯器通常會輸出一個警告,因爲它並沒有真正完成任何事情。

4實施例1

int i1 = 1;    // definition, external linkage 
static int i2 = 2;  // definition, internal linkage 
extern int i3 = 3;  // definition, external linkage 
int i4;     // tentative definition, external linkage 
static 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 disagreement 
extern int i1;   // refers to previous, whose linkage is external 
extern int i2;   // refers to previous, whose linkage is internal 
extern int i3;   // refers to previous, whose linkage is external 
extern int i4;   // refers to previous, whose linkage is external 
extern int i5;   // refers to previous, whose linkage is internal 
+0

如果它確實沒有完成任何操作,爲什麼它被允許? – Jay 2010-02-27 20:01:22

+0

許多關鍵字和語法碰巧是任何地方的默認解釋。例如,在一個函數'int i;'和'auto int i;'中是相同的定義。雖然添加'auto'並不能完成任何特定的操作,但它允許一致地使用存儲類說明符。 – DigitalRoss 2010-02-27 20:07:11

0

extern關鍵字指示給定的變量在不同的模塊分配。它與訪問無關。分配給extern變量是完全合法的。

+0

首先,OP中的變量被分配在* this *模塊中,因爲OP中的聲明實際上是一個*定義*。 'extern'並不是說某些東西是「在不同的模塊中」。它只是提供了一些外部聯繫。其次,OP中沒有任務。這是一個初始化,而不是賦值。 – AnT 2010-02-27 20:11:25

+0

請注意,這是和示例初始化不分配。 – Clifford 2010-02-27 23:30:28

0

extern關鍵詞的目的是給實體外部鏈接。無論是用於a還是定義中的聲明都沒有區別。您發佈的代碼絕對沒有錯誤。

如果你喜歡去想它在「出口與進口」的條款,然後extern關鍵字應用於非定義聲明意味着我們進口在其他一些轉換單元中定義的實體。當extern關鍵字適用於定義,這意味着我們是導出此實體將由其他翻譯單元使用。 (雖然值得注意的是「出口與進口」並不完全是考慮C鏈接概念的標準方式)。

您不會看到定義中使用的關鍵字的原因很多時候是因爲在C文件範圍定義默認具有外部鏈接。所以寫

extern int i = 10; 

是有效的,但多餘的,因爲它相當於普通

int i = 10; 

然而,不時在實際的代碼,你可能會使用與函數聲明和定義該關鍵字的人看到,儘管它在那裏也是多餘的

extern void foo(int i); /* `extern` is superfluous */ 
... 
extern void foo(int i) /* `extern` is superfluous */ 
{ 
    /* whatever */ 
} 
+0

我對此投了反對票,爲時太晚而無法糾正。爲了解決這個問題,我發現了另一個你給我喜歡的答案,並加以補充。不是它看起來像你需要它;)道歉。 – Clifford 2010-02-27 23:48:51

4

以下代碼;

extern int i ; 

聲明變量i,但不實例化。如果它不在同一個編譯單元中定義,鏈接器將嘗試從構成最終可執行文件的目標文件和庫中解析它。

但是你的例子:

extern int i = 10 ; 

初始化的對象,因此也必須將它實例。在這種情況下,extern關鍵字是多餘的,因爲該對象在相同的編譯單元中初始化(實際上是相同的語句)。它等效於:

extern int i ; // redundant 
int i = 10 ; 

雖然在最後的例子extern關鍵字是多餘的,它完全等同於你所擁有的,當一個全局變量是聲明在頭文件在一個實例源文件也包含該頭文件(因爲它應該允許編譯器執行類型檢查)。

可以測試此如下:

extern int i ; 
int main() 
{ 
    i = 10 ; 
} 

上面將導致未解決的變量i的接頭錯誤。鑑於:

extern int i = 10 ; 
int main() 
{ 
    i = 10 ; 
} 

將鏈接沒有問題。