[英]Why main() cannot be declared as a static in C?
為什么main必須被聲明為具有外部鏈接?
為什么它不應該是靜態的?
什么是外部聯系?
因為您將啟動文件鏈接到您的程序,該程序包含(通常)調用main的匯編程序代碼。 如果main是靜態的,那么該代碼將無法調用main。
external linkage
意味着其他所謂的translation-units
可以在自己的翻譯translation-units
中看到您的符號被聲明為extern。 所以,你的主要是extern,它的翻譯單元符號表中會有一個表示其地址的條目。 其他翻譯單元將能夠在他們想要呼叫主要時跳轉到該地址。
static linkage
意味着您的符號是嚴格的翻譯單位本地。 這意味着其他translation units
將無法看到該符號。 因此,具有靜態鏈接的符號可以多次出現在不同的翻譯單元中,並且它們不會彼此沖突,因為它們是本地的。
編輯 :通常,編譯器從翻譯單元生成的文件特定於該特定編譯器。 對於linux上的gcc,通常使用ELF對象格式。 您可以使用readelf -sW <file>.o
查看其符號表(下面的簡單測試文件):
test.c的
void bar(void);
static int foo(void) {
return 1;
}
int main(void) {
bar();
return foo();
}
這是readelf的輸出:
Symbol table '.symtab' contains 10 entries:
Num: Value Size Type Bind Vis Ndx Name
0: 00000000 0 NOTYPE LOCAL DEFAULT UND
1: 00000000 0 FILE LOCAL DEFAULT ABS test.c
2: 00000000 0 SECTION LOCAL DEFAULT 1
3: 00000000 0 SECTION LOCAL DEFAULT 3
4: 00000000 0 SECTION LOCAL DEFAULT 4
5: 00000000 10 FUNC LOCAL DEFAULT 1 foo
6: 00000000 0 SECTION LOCAL DEFAULT 6
7: 00000000 0 SECTION LOCAL DEFAULT 5
8: 0000000a 36 FUNC GLOBAL DEFAULT 1 main
9: 00000000 0 NOTYPE GLOBAL DEFAULT UND bar
您可以看到main函數和main調用的靜態foo函數。 還有一個函數被調用,該函數未在文件中定義,但在另一個目標文件中定義。 由於目標文件尚未最終鏈接,因此這些函數尚未分配最終地址。 在最終鏈接之后,這些將被安排到可執行文件中並將分配地址。 目標文件具有用於調用尚未定義的函數的條目,因此在鏈接文件時,這些調用指令可以存儲最終地址( readelf -r <file>.o
):
Relocation section '.rel.text' at offset 0x308 contains 1 entries:
Offset Info Type Sym.Value Sym. Name
0000001c 00000902 R_386_PC32 00000000 bar
代碼的真正起點隱藏在C運行時庫中。 此運行時庫調用main()例程。 為了讓鏈接器將C RTL調用與main()函數連接,它需要在文件外部可見。
外部鏈接就是這樣:它意味着有問題的名稱作為目標文件導出的一部分可見。 鏈接器的工作是連接所有導入和導出,以便沒有未完成的導入。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.