2012-02-12 55 views
2

請考慮以下C函數。
是否打開大括號以創建局部範圍使編譯器在堆棧上創建記錄以維護範圍中聲明的變量?堆棧上的本地範圍記錄

void function() 
{ 
    int q,r; 
    ... 
    { 
     int i = 0; 
     int j = 3; 
     q = j + 1; 
    } 
    ... 
} 

如果是這樣,編譯器採取同樣用,而塊?

例如:

void function() 
{ 
    int q,r; 
    ...  
    while(conditions) 
    { 
     int i = 0; 
     int j = 3;  
     q = j + 1;  
    } 
    ... 
} 

回答

4

不是由C標準中指定的堆疊的佈置。

花括號({})引入了一個新的範圍,所以原則上,這可以在堆棧上創建一個新框架。但編譯器可能會選擇優化這個開銷。

1

這取決於編譯器。良好的現代編譯器會優化這些代碼。這將在編譯時計算

int j = 3; 
q=j+1; 

和製造類似

q=4; 

同爲第二個例子。變量j將被放置在堆棧中,甚至可能放入一個寄存器中,其值設置爲3,然後通過循環迭代進行處理。

1

{}被稱爲複合語句(也稱爲塊),它引入了一個新的塊範圍。這意味着在這裏:

void function(void) 
{ 
    int q,r; 
    ... 

    { 
     int i = 0; 
     int j = 3; 
     q = j + 1; 
    } 
    ... 

}

qr在函數結束時被銷燬; ij在本地塊範圍的末尾被銷燬。自動對象的生命週期僅限於聲明的塊。

對於喜歡while語句循環語句,這是完全一樣的,while陳述的定義爲:

while (expression) statement 

如果您在while使用的語句複合語句(塊)也將引入新的範圍。

現在在堆棧級別上,C不需要堆棧,因此它的實現細節。

+0

所以q,r和i,j可以在不同的記錄上創建? – GionJh 2012-02-12 12:50:36

+0

@ user986437'q','r'和'i','j'具有不同的詞彙範圍和不同的生存期。 – ouah 2012-02-12 12:53:23

+0

請注意,while循環中的'i'和'j'在循環的每次迭代中都重新初始化。 – 2012-02-12 13:15:41

0

根據我以前見過的行爲,我會說「可能不是」。 IME,只爲所有函數的變量創建一個單獨的堆棧框架,而不管它們在函數中的作用域如何。

受限範圍是編譯器在翻譯時強制執行的事情;在運行時並沒有真正的需要。

+0

我看到...請幫我清楚這一點。讓我們假設我有一臺帶有幾kb RAM的電腦,會爲程序員創建的每個範圍使用一個記錄,以幫助大型程序在我的電腦上運行? – GionJh 2012-02-12 15:38:57

+0

語法更正* kbytes – GionJh 2012-02-12 16:52:52

+0

如果您真的對內存有限制,則爲每個範圍創建整個堆棧幀可能會使情況變得更糟*。更不用說它會造成運行時性能損失。 – 2012-02-12 22:59:49