2013-07-10 75 views
1

我對使用extern關鍵字和C語言中的變量有一些疑問。我確實經歷了與這個問題相關的鏈接。不過,也有我沒有收集很好
extern變量是如何定義的?

#include<stdio.h> 
    main() 
    { 
    extern int i; 
    printf ("\n%d ",i)) ; 
    } 
    int i = 31 ; 

在上面的代碼還是有幾件事情,如何我得到它的定義語句之前打印?
現在在下面的代碼:

#include<stdio.h> 
int x = 21 ; 
main() 
{extern int i; 
i=20; 
printf ("\n%d ", i) ; 
} 

是不是語句 「我= 20;」一個定義聲明?我得到這個錯誤。是因爲我試圖改變在其他源文件中定義的變量嗎?如果是這種情況,那麼「int i = 31;」的說法如何?在最上面的代碼片段正確使用?

另外,我讀了「int i;」是一個定義。我沒有真正遵循如何。

回答

5

在您的第一個程序中,打印語句基於extern int i聲明打印i的值。這與基於其原型聲明調用函數而不看其定義相似。編譯器生成代碼以檢索名爲i的全局變量中的值。符號在鏈接時解析爲正確的變量和地址。

在您的第二個程序中,未提供i的定義,僅提供extern int i聲明,並嘗試使用i = 20設置其值。在鏈接時失敗,因爲沒有定義,所以嘗試解析對全局變量的引用失敗。將i = 20更改爲int i = 20而不是在函數main()的範圍內創建名爲i的局部變量,並且不再引用全局聲明的extern int i

當在全局範圍使用int i;時,它被視爲聲明並可被視爲一種定義。使用初始值設定項聲明的全局變量,如:

int i = 20; 

始終視爲定義。只有這種類型的定義是允許的,即使每個定義都使用相同的初始值。但是,

int i; 

被視爲聲明。如果出現這些聲明中的一個以上,則它們全部被視爲相同變量的聲明。同時,如果不存在使用初始值設定項的聲明,則該變量隱式定義爲初始值爲0,並且鏈接程序將能夠解析對其的引用。

1

在第二個程序中,您沒有在任何地方定義變量,而不是在main之外定義變量,相反,您已經在main中定義了變量,以便獲取該錯誤。

但是在第一個程序中,您定義了一個變量,並且這個變量在主體之外,所以您不會看到這個錯誤。程序看起來在主體之外並找到它的定義。

int i;是一個變量定義聲明都用於AUTO變量(即,Ë內部主要或所有的功能),但不爲extern變量,你必須聲明外部變量是這樣的:

extern int i;

,然後定義之外的主要是這樣的:

int i;

0

extern背後的想法是,你告訴編譯器你將使用一個已經在使用範圍之外定義的變量。

在第二種情況下沒有多大意義,因爲i被定義爲局部變量。 如果你想將它定義爲全局的,就像你在第一種情況下那樣,那就沒問題。

如果我能表現出一個非常簡單的(人爲)的情況下使用extern

的main.c:

#include <stdio.h> 

extern int a; /* we tell the compiler that a will come from outside the scope of where it is used */ 

int main() 
{ 
    printf("%d\n", a); 

    return 0; 
} 

由source.c:

int a = 3; /* we define a here */ 

你再編譯.c這樣的文件:

$ gcc main.c source.c 

此輸出3

您可能還想閱讀this文章。

+0

我認爲兩者都應該編譯,但第二個將無法鏈接(*啓動鐺測試它*) – Christoph

+1

好吧,第一個例子未能編譯,但不是因爲變量聲明 - 有一個多餘的右括號... – Christoph

+0

@Christoph第二個失敗是因爲說'我'是'extern',但實際上並沒有提供它在同一時間使用它。將所有使用'i'的線條註釋掉'extern'一個,它會很好地編譯。 – Nobilis

1

變量/函數的聲明只是聲明變量/函數存在於程序中的某處,但內存未分配給它們。

回到定義,當我們定義一個變量/函數,除了聲明的作用之外,它還爲該變量/函數分配內存。

所以在第一個程序中,int i = 31之外的main()定義了變量i。然後這個變量僅僅在main()中聲明爲extern變量。因此該程序起作用。

在第二個程序中,沒有在別處定義變量i,它直接聲明爲extern變量。因此它給出了一個錯誤。