2011-03-23 72 views

回答

2

從技術上講應該是這樣的,但這種使用方式已經存在多年並且不可能根除(已經嘗試過;每個供應商經常會決定使其成爲一個錯誤,並在前100個錯誤報告後恢復)。迂迴地,.h文件應該聲明它extern一個.c/.cpp文件應該定義它。

簡而言之,當您未指定頂級變量的鏈接(static,extern等)時,它會被聲明爲「通用」。在鏈接時,如果所有對該變量的引用都是相同的大小(和類型,如果可用),那麼它將被分配一次,並且所有引用都指向它。如果鏈接器爲同一個變量找到不同的大小/類型/鏈接,則會引發錯誤。

編輯:這顯然混淆了人。在這裏:

jinx:1714 Z$ cat foo.h 
int foo; 
extern void bar(); 
jinx:1715 Z$ cat foo.c 
#include "foo.h" 

int 
main(int argc, char **argv) 
{ 
    bar(); 
    return 0; 
} 
jinx:1716 Z$ cat bar.c 
#include "foo.h" 

void 
bar(void) 
{ 
    return; 
} 
jinx:1717 Z$ gcc -Wall foo.c bar.c -o foo 
jinx:1718 Z$ ./foo 
jinx:1719 Z$ _ 

注完全沒有錯誤的約int foo被多次定義。 這個是我一直想說的。

+0

你是說在'module.h'中'struct list_head source_list;'是一個變量的定義嗎? – ssmir 2011-03-23 12:31:23

+0

@ssmir:這是一個聲明,而不是一個定義(除非它被初始化,如其他頁面所指出的那樣)。它隱含地標記爲「通用」,所以鏈接器將(只要所有聲明都相互兼容)自己定義它。 – geekosaur 2011-03-23 12:33:16

+0

好吧,它是一個全局變量的聲明? – ssmir 2011-03-23 12:40:07

0

確實應該有一個extern。但是,該變量沒有明確的定義,所以編譯器將其標記爲extern。

,如果你有

struct list_head source_list = { 0 }; 

你會得到一個鏈接錯誤......因爲這確實每翻譯單元(並因此連接抱怨)一次定義符號。

+0

這是一個定義,也就是所謂的臨時性定義。 – 2011-03-23 12:21:08

1

struct list_head source_list;字段在其他結構中聲明,因此它們不是符號。

其他(頂級)結構的聲明有不同的名稱,所以也可以。

編輯

注意,所有變量它這個頭真的打上extern

1

這種情況的術語是「試探性定義」:

的標識符用於一個 對象的聲明具有文件作用域沒有 初始化,並且沒有 存儲類說明或與 存儲級說明符static, 構成 暫定義。如果翻譯單元包含一個或多個用於一個 標識符更 暫定定義,和翻譯單元包含該標識符的外部 定義,然後 行爲是完全一樣,如果翻譯單元包含 標識符的 文件範圍聲明與爲0

因此,這是用C良好限定的複合類型作爲 翻譯單元的端部,具有一個初始化 等於(但通常皺眉)。

+0

但是即使是暫定義也不能定義兩次,對嗎? – 2011-03-23 12:29:35

+0

@ compile-fan聲明在你的問題中沒有聲明任何類型的變量,它只是聲明瞭一個結構體的字段。此外,它聲明的結構不會產生符號。這也不是一個試探性的定義。 – ssmir 2011-03-23 13:11:53

+0

@編譯風扇,是的,它可以。看,它說:「一個或多個試驗性的標識符定義」。 – 2011-03-23 13:12:21

相關問題