以this file爲例,有像許多非EXTERN結構:爲什麼non-extern可以在C/C++中使用.h文件?
struct list_head source_list;
當這個頭文件是由多於一個編譯單位包括如何能行嗎?
應該有錯誤報告,相同的符號被定義兩次,對嗎?
以this file爲例,有像許多非EXTERN結構:爲什麼non-extern可以在C/C++中使用.h文件?
struct list_head source_list;
當這個頭文件是由多於一個編譯單位包括如何能行嗎?
應該有錯誤報告,相同的符號被定義兩次,對嗎?
從技術上講應該是這樣的,但這種使用方式已經存在多年並且不可能根除(已經嘗試過;每個供應商經常會決定使其成爲一個錯誤,並在前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
被多次定義。 這個是我一直想說的。
確實應該有一個extern
。但是,該變量沒有明確的定義,所以編譯器將其標記爲extern。
,如果你有
struct list_head source_list = { 0 };
你會得到一個鏈接錯誤......因爲這確實每翻譯單元(並因此連接抱怨)一次定義符號。
這是一個定義,也就是所謂的臨時性定義。 – 2011-03-23 12:21:08
此struct list_head source_list;
字段在其他結構中聲明,因此它們不是符號。
其他(頂級)結構的聲明有不同的名稱,所以也可以。
編輯
注意,所有變量它這個頭真的打上extern
。
這種情況的術語是「試探性定義」:
的標識符用於一個 對象的聲明具有文件作用域沒有 初始化,並且沒有 存儲類說明或與 存儲級說明符static, 構成 暫定義。如果翻譯單元包含一個或多個用於一個 標識符更 暫定定義,和翻譯單元包含該標識符的外部 定義,然後 行爲是完全一樣,如果翻譯單元包含 標識符的 文件範圍聲明與爲0
因此,這是用C良好限定的複合類型作爲 翻譯單元的端部,具有一個初始化 等於(但通常皺眉)。
但是即使是暫定義也不能定義兩次,對嗎? – 2011-03-23 12:29:35
@ compile-fan聲明在你的問題中沒有聲明任何類型的變量,它只是聲明瞭一個結構體的字段。此外,它聲明的結構不會產生符號。這也不是一個試探性的定義。 – ssmir 2011-03-23 13:11:53
@編譯風扇,是的,它可以。看,它說:「一個或多個試驗性的標識符定義」。 – 2011-03-23 13:12:21
「編譯單元」通常稱爲「翻譯單元」。 – 2011-03-23 12:03:52