2016-10-26 27 views
1

https://www.quora.com/What-are-the-types-of-linkages-in-C-programming應該用外部關鍵字定義一個帶有外部連接的變量嗎?

外部聯動,意味着該變量可以在某處定義 否則你正在使用的文件,這意味着你可以定義 任何其他翻譯單元,而當前的一個內外部(你當在其他 源代碼中定義它時, 將必須使用關鍵字extern。

內部連接,意味着變量必須在 翻譯單元範圍來限定,這意味着它應該或者在包含的庫中的任 來定義,或者在同一文件中的範圍。

無連接,指向默認功能和大括號範圍,例如 定義一個函數內的自動變量,這將使 變量只能在該函數的範圍內訪問。

需要注意的是:

任何全局對象是由外部默認鏈接,您可以通過使用關鍵字static禁用。

默認情況下,任何常量全局對象都是內部鏈接的,您可以使用關鍵字extern禁用該對象。

假設一個全局變量在file1中定義,我想在file2中使用它。

  1. 在文件1,應在全局變量與關鍵字 extern界定?

    的報價上面似乎自相矛盾:

    • 「你將不得不在其他源代碼定義它時使用的關鍵字爲extern」似乎是說應該。

    • 「默認情況下,任何全局對象都是外部鏈接的」似乎表示不需要。

  2. file2中,我必須聲明全局變量與關鍵字extern

+0

我不認爲這兩種情況都是強制性的。第一句話可能恰好是錯的。讓我檢查std – HuStmpHrrr

+0

一個是外部聯繫,一個是外部聯繫。我認爲有一個不同的。 – Danh

+1

您需要使用'extern'來定義變量的語句不正確。您只需要在引用其他地方定義的變量的文件中使用'extern'。 –

回答

1

C11草案,6.2.2,第四部分,規定:

對於在一個範圍的存儲類說明的extern聲明的標識符,其中該標識符的 事先聲明是可見,31)如果在先聲明指定了內部或外部鏈接,則後面聲明中標識符的鏈接與先前聲明中指定的鏈接相同。如果沒有事先聲明可見,或者先前的聲明沒有指定鏈接,則該標識符具有外部鏈接。

我不認爲有或沒有extern關鍵字會有任何差異。一些實驗還表明:

以下2編譯:

extern int a; 
extern int a; 

int a = 20; 

extern int a; 
int a; 

int a = 20; 

,但不是這一個:

extern int a; 
int a = 10; 

int a = 20; 
然而

,我有一些印象,一旦我閱讀有關動態鏈接涉及Windows時的不同行爲。雖然我找不到它。如果有人能證實,這將是很好的。

3

tldr:你應該聲明變量,與extern,在由File1和File2都包含一個頭文件。你應該在中定義這個變量只在file1中。爲了定義變量,你聲明沒有extern(也沒有static)。


聽起來你已經得到了extern關鍵字和standardese術語「外部鏈接」混爲一談。

只要該變量的聲明對該函數可見,就可以從程序中的任何函數訪問具有「外部鏈接」的變量。相比之下,可以從一個「翻譯單元」(一個源文件及其包含的所有文件)訪問至多具有「內部鏈接」的變量,而具有「無鏈接」的變量僅在單個功能中可見。 (函數內聲明的變量static是否被認爲有內部鏈接或沒有聯繫,我不記得了我的頭頂。)

extern關鍵字,應用於變量聲明,有影響。首先,它保證該變量將被賦予外部鏈接,即使該聲明在函數內(不這樣做)。其次,更重要的是,它使聲明不是定義。這意味着,如果你有這兩個文件

/* file1.c */ 
extern int foo; 

/* file2.c */ 
extern int foo; 
int main(void) { return foo; } 

他們的組合不是一個有效的程序。你會從鏈接器中得到一個錯誤信息,可能是讀取「undefined reference to foo」。

要使這個程序有效,您必須從中刪除externfoo這兩個聲明。該聲明隨後成爲定義,並且該程序將鏈接。 (另外,該聲明就可以給出一個初始化,如果你希望它有在啓動時比0以外的值。)

如果您從foo的定義都extern,其結果是, IIRC,實施定義。一些C編譯器會將它們合併成一個單一的全局變量,而另一些則會發出鏈接時錯誤。有時行爲取決於變量是否具有初始值。

這是OK寫

/* file1.c */ 
extern int foo; 

/* file2.c */ 
extern int foo; 
int foo; 

這可以讓你把一個頭文件中的extern聲明這兩個.c文件包括,從而降低未來有不一致的類型(如果發生這種情況的聲明的風險該程序將顯示未定義的行爲)。

+0

來澄清** define **的意思,相比聲明? – HuStmpHrrr

+0

@HuStmpHrrr修改後的答案是否足以說明問題? – zwol

1

您引用的文字有很多錯誤。我會建議不要依賴該網站的信息。

(在其他源代碼中定義時,您必須使用關鍵字extern)。

不然,除非static關鍵字使用(或不使用符與他們正在重新宣佈已經與static關鍵字聲明的東西)的文件範圍的定義具有外部連接。

在定義中可能包含冗餘extern,但是還必須有一個初始化器(否則它將是一個聲明而不是定義)。

內部鏈接意味着變量必須在翻譯單元作用域中定義,這意味着它應該在任何包含的庫中定義,或者在相同的文件範圍內定義。

推測這意味着「包含標題」,而不是「包含的庫」。

默認情況下,任何常量全局對象都是內部鏈接的,您可以使用關鍵字extern禁用該對象。

這是錯誤的,除非聲明爲static,否則「全局對象」具有外部鏈接。作者可能將C與C++混淆了(在後者中,const全局對象具有內部鏈接,除非另有說明)。


假設一個全局變量在文件1定義,我想file2中使用它。

// file1.h (or any other header) 
extern object_t obj; 

// file1.c 
#include "file1.h" 
object_t obj; // or: extern object_t obj = { 1, 2, 3 }; 

// file2.c 
#include "file1.h" 
相關問題