2013-02-03 30 views
9

可能重複:
Effects of the `extern` keyword on C functions混亂關於與函數定義的extern用C

好了,現在幾個小時我已經讀了很多關於extern關鍵字是什麼意思。還有最後一件事情讓我無法找到任何有關的信息。 據我所知extern關鍵字基本上告訴編譯器,變量或函數只是一個聲明,並且它是在某個地方定義的,所以它不必擔心,鏈接器會處理它。

而且打字時由編譯器(我用gcc 4.2.1)所產生的警告:

extern int var = 10; 

支持這一點。用extern這應該只是一個聲明,所以它是不正確的。

然而,這是混淆了我的事情是打字時沒有警告或任何東西:

extern int func() {return 5;} 

這是一個定義,它應該產生同樣的警告,但事實並非如此。對此的唯一解釋是在此處找到的是該定義覆蓋了extern關鍵字。但是,遵循這個邏輯,爲什麼它在變量定義時不會覆蓋它?或者,當與變量一起使用時,關鍵字是否有特殊含義?

如果有人向我解釋這一點,我將不勝感激。謝謝!

+3

最後一個分號正在擾亂我。 –

+1

看看[這個鏈接]是否有幫助(http://stackoverflow.com/questions/856636/effects-of-the-extern-keyword-on-c-functions)有幫助。 –

+1

問題必須是變量的初始化 – nabroyan

回答

5

關鍵字extern只有在與變量一起使用時的確具有特殊含義。使用extern與函數原型是完全可選:

extern void foo(int bar); 

相當於

void foo(int bar); 

當你聲明/定義一個函數,你有兩個選擇:

  1. 只提供一個聲明(即原型)或
  2. 提供一個定義,該定義也可用作缺少原型的聲明。

有了變數,但是,你有三種選擇:

  1. 只提供一個聲明,
  2. 提供的默認初始值的定義:沒有= 10部分int var;,或
  3. 提供一個使用特定的初始化程序定義:int var = 10

Sin ce只有兩個功能選項,編譯器可以區分那麼不用使用extern關鍵字。任何沒有static關鍵字的聲明默認爲extern。因此,extern關鍵字在所有函數聲明或定義中都將被忽略。

但是,使用變量時,需要使用關鍵字來區分#1和#2。當您使用extern時,它是#1;當你不使用extern時,它是#2。當您嘗試向#3添加extern時,這是一個警告,因爲它仍然是一個定義,並且extern被忽略。

所有這些都有所簡化:您可以在同一個編譯單元中多次提供聲明,並且可以在全局範圍或塊範圍內提供它們。有關完整的詳細信息,請查看C標準的第6.7.9節。

+0

有關對象(而非變量)聲明的聲明不正確。在文件範圍內:'int x;'是具有外部鏈接的對象的臨時定義,'extern int x;'是具有外部鏈接的對象聲明,int x = 3;'extern int x = 3 ;'都是具有外部鏈接的對象的定義。在塊範圍內:'int x;'是沒有鏈接的對象的定義,'extern int x;'是具有外部鏈接的對象聲明,int x = 3;'是一個沒有鏈接的對象的定義鏈接和'extern int x = 3;'是不允許的,由C 2011 6.7.9 5. ... –

+0

以上假設每個聲明是標識符第一次出現在該範圍內。否則,會有複雜性。例如,'static int x; extern int x;'是允許的,後者'x'與前者'x'相同。另外,儘管一些編譯器在文件範圍內發出了'extern int x = 3;'的警告,但在C 2011的示例中它明確顯示爲有效6.9.2 4. –

+0

@EricPostpischil我編輯了答案,感謝評論。 – dasblinkenlight

3

但是,遵循該邏輯,爲什麼在它是變量定義時不會覆蓋它?或者,當與變量一起使用時,關鍵字是否有特殊含義?

變量和函數之間的差別在於

void foo(); 

是一個函數聲明,

int i; 

是可變定義。

如果在多個文件中有變量定義,那麼編譯器會多次爲該變量生成存儲(並且很可能會出現鏈接器錯誤)。功能並非如此。

+1

我認爲當我們有'extern int x = 1;'這看起來像一個聲明和一個具有初始化器的定義時,這是最令人困惑的。 –

+0

在文件範圍內,'int i;'是一個暫時的定義,而不是一個定義,它既不會產生多次存儲也不會導致鏈接錯誤。 –