2014-01-15 197 views
1

我橫跨這片C代碼傳來:多個實例

main(){ 
static int i=0; 
i++; 

if(i<=5){ 
     int i = 3; 
     printf(" %d",i); 
     main(); 
    } 
} 

1.首先,我期望將該代碼作爲有多個給編譯錯誤變量的定義i。但是,它編譯併成功運行並提供了此輸出。

3 3 3 3 3 

2.觀察輸出,恰好印刷5倍,這意味着循環從0-5因此暗示計數,對於如果條件,第一定義(靜態)使用i

然而,正在打印的值是3 這是i的第二定義。

所以變量標籤i指的是內存中的兩個不同實例。一個用作循環計數,執行增量操作,另一個用於打印值。

我能以某種方式解釋這個問題的唯一辦法是:

  1. int i = 3(第二定義),在每一個遞歸調用重複。 i的實例是在函數被調用時創建的,並且在下一次遞歸調用時被終止。 (由於靜態範圍)。 printf使用這個實例,因爲它是最新的定義(?)

  2. 當進入遞歸的一個新的水平,i++正在做。由於沒有其他方法可以解決此問題,因此它使用i的靜態「實例」,該靜態「實例」在代碼中仍處於「活動」狀態,因爲它被定義爲靜態。

但是,我無法精確地指出這是如何工作的......任何人都可以解釋這裏發生了什麼,在代碼和內存中?

這裏的編譯器如何完成變量綁定?

+0

一個字:範圍。 – devnull

+0

閱讀[可變陰影](http://en.wikipedia.org/wiki/Variable_shadowing)。 –

+1

你沒有'while'環... – starsplusplus

回答

4

內部範圍獲勝。

實施例:

int i = 1; 
void foo() { 
    int i = 2; // hides the global i 

    { 
     int i = 3; // hides local i 
    } 
} 

此行爲是設計。你可以做的是使用不同的命名約定變量的作用域:

  • 全局/靜態
  • 函數參數
  • 當地人
  • 類/結構成員

一些編譯器會發出警告如果你在同一個函數中隱藏一個變量(例如函數參數和常規局部變量)。所以你在編譯器上的最大警告級別。

+0

謝謝,我一直認爲具有相同標識符的多個定義會導致編譯錯誤。在打印每個定義和1 2 3後,用printf語句測試您的代碼。 –

+0

同一範圍內的2個定義是錯誤的。函數arguemnt與局部變量(在本例中爲'int i = 2')具有相同的作用域 – egur

1

{} if語句創建一個新塊範圍,當你在該範圍內聲明i隱藏i在外部範圍。新的範圍並沒有啓動,直到{因而if語句是指i在外部範圍。

隱藏被覆蓋在C99標準牽伸部6.2.1作用域標識符段落說(重點礦山)的:

[...]如果標識符指定在兩個不同的實體同名 空間,範圍可能重疊。如果是這樣,則一個實體(內部範圍)的範圍將是另一個實體(外部範圍)範圍的嚴格子集 。在內部範圍內, 標識符指定在內部範圍內聲明的實體; 在外部作用域中聲明的實體在內部作用域內隱藏(並且不可見)。

+0

在代碼中沒有看到'while'? – starsplusplus

+0

@ user3156863這是一個錯字,我甚至說*如果聲明*在開始時不確定爲什麼我輸入*而最後是*。 –

1

編譯器總是用一個變量的大多數地方版當該名稱的多個變量的存在。

外循環,第一i是存在唯一的,所以它是檢查之一。然後,一個新的i被創建,用值3。在這一點上,只要你談談i它會假設你的意思是第二個,因爲這是更當地化。當您退出循環,第二i將走出去的範圍,刪除,所以如果你又開始談論i這將是第一個。