2016-02-04 76 views
1

爲什麼下面的代碼會被編譯? 何時'num'變量獲取其值?'extern'關鍵字會使下列代碼合法嗎?

#include <stdio.h> 

extern int num; 

void main() 
{ 
    printf("%d", num); //prints 3 
} 

int num = 3; 

例子:Live Code

+4

如果我刪除'extern',會有什麼問題? –

+0

你有沒有使用'extern'在多個文件中使用變量?這工作原理相同,但在一個文件中。 – immibis

+0

@SouravGhosh代碼不會編譯 – Nemmy

回答

2

在你的代碼,

extern int num; 

被稱爲聲明。 OTOH,

int num = 3; 

是具有顯式初始化的定義。此聲明設置的值。該值在編譯時決定,並在main()開始執行之前設置。

也就是說,void main()應該是int main(void),至少要符合標準。

+0

OP在問什麼時候。答案是「就在'main'運行之前」。 –

+0

是的,我知道聲明和定義之間的區別,但這裏的要點是'num'在調用main之後被聲明;實際上,如果你刪除了extern關鍵字,它將不會編譯! – Nemmy

+0

這裏,它與函數原型相似。 'extern'使它可用,儘管它的價值(實現)是在後面定義的。編譯器確保它的值在'main'運行之前被設置,儘管它在源文件中被定義。 –

0

extern與聲明一起使用。它告訴編譯器,這個東西將在其他地方定義。當你有多個使用相同變量或函數的文件時,這很有用。你可以在頭文件中放入一個extern聲明,並在源文件中定義共享變量/函數。

如果您從代碼中刪除extern您將定義兩次num,這是不允許的。要擺脫extern聲明,只需將您的int num = 3;置於文件的頂部。

2

它的工作原理,因爲你已經聲明num因此它可以在函數的代碼進行命名,因爲你在命名空間內,使得它在靜態初始化時間,這僅僅是main是前初始化定義它執行。

在這個意義上,你的程序作爲當前寫入是從以下很難區別:

#include <stdio.h> 

int num = 3; 

void main() 
{ 
    printf("%d", num); //prints 3 
} 

「去哪兒」你初始化變量不是特別重要,只要假以時日,你出現之前嘗試使用它。

順便說一句,您必須使main返回int,而不是void

1

extern標記後面定義的變量聲明。定義int num = 3;部分是爲變量實際分配內存並設置其值(它也作爲聲明加倍)。 C/C++在使用之前聲明,如果你沒有這樣做extern int num;那麼num不會在你使用它的地方聲明。您當然也可以刪除extern一行,並將num的定義提高到main()以上。

這裏有兩件事情發揮作用。在編譯期間,num必須在使用之前在源文件中的某一點聲明。至於什麼時候它被賦值,這是在程序加載過程中發生的。在num之類的文件範圍(在任何函數之外)的所有變量都分配了它們的內存,並且在調用main()之前初始化了它們的值。如果它們在定義中沒有被賦予一個值,那麼它們可能包含任何東西,所以不要對未初始化變量的值做任何假設。你也不能對它們初始化的順序做任何假設,所以當初始化一個像這樣的變量時,不要引用其他文件範圍變量。