2013-04-28 118 views
2

我注意到,您可以在括號中包含隨機代碼塊,它將所有聲明的變量本地化。關於C編譯中的括號

我的問題是,這些變量在程序離開'括號區'之後是否從程序中解放出來?通過這個我的意思是,他們創建和銷燬堆棧類似於函數?

我想看看一些的拆卸弄明白,但我不擅於閱讀編譯器生成組件(即應該有一個獨立的教程)

編輯:

這是什麼意思:

int main(){ 

    { 
     int i = 0; 
    } 
    return 0; 
} 

我知道什麼功能。我不是在討論函數,我也不是在要求任何人告訴我函數是什麼。

+7

你真的應該花時間**閱讀一本好的* C *編程書**。它解釋了這些事情比我們在幾分鐘內做得好得多。 – 2013-04-28 07:12:46

+2

爲什麼我會被拒絕?我知道C,我錯過了一些基本的東西嗎? – tay10r 2013-04-28 07:14:16

+1

讀取生成的程序集(如果使用GCC,不要忘記使用'gcc -Wall -S -fverbose-asm'編譯)無法提供幫助:編譯器有很多關於它能做什麼的自由... – 2013-04-28 07:14:38

回答

2

嵌套作用域中的自動變量在該作用域之外是不可訪問和無效的。從邏輯上講,它們被破壞;沒有便捷的方式可以告訴你實際發生了什麼。通過指定指向作用域內靜態變量的指針(在作用域之外定義),可以在作用域之外訪問作用域內的靜態變量。

限制變量的範圍可以使程序更容易理解。你不必在別處尋找他們使用的地方。這與使函數靜態類似;你不必在目前的源文件之外尋找它們的用途(除非它們用於初始化指向在文件外被引用的函數的指針)。通常沒有運行時效率增益。

您可能會看到與VLAS一個好處:

{ 
    int n = 1000; 
    { 
     int array1[n]; 
    } 
    { 
     int array2[n]; 
    } 
} 

在這裏,你可以合理地希望編譯器只在堆棧上1000個整數分配空間;如果數組不在單獨的作用域中,它將不得不爲堆棧中的2000個整數分配空間。 (如果示波器是不相交的,你可以用普通數組或普通變量得到「空間共享」。)

+1

「從邏輯上說,它們被摧毀了,沒有便捷的方式來告訴你實際發生了什麼」 - 這正好回答了我的第一個問題。謝謝 – tay10r 2013-04-28 07:20:15

4

在程序離開'括號區'後,這些變量是否從程序中釋放出來?

如果變量是自動/局部變量,那麼他們是。

這是否使程序更高效?

或許不會,最現代的編譯器將優化代碼相同的效果,即使沒有範圍,但這樣做明確地使你的代碼更有條理。讓代碼的讀者知道變量的活動範圍和訪問範圍會更直觀。您編寫的代碼不僅適用於編譯器,而且適用於將來的代碼用戶。


每個支架{打開與}結束的範圍,範圍內聲明的所有局部變量只範圍內仍然存活。

對於如:函數內部的內部範圍內{ }

void doSomething() 
{ 
    { 

     int i; 
    } 

} 

i生活,不存在超越它。
由於您可以使用範圍{ }控制變量的使用期限可見性,因此使用此功能。

+1

我不同意。實現不需要釋放變量 - 這沒有任何確切的含義。你甚至可以想象C(低效率)解釋器在一些垃圾收集堆中分配它的調用幀(參見Appel的舊論文*垃圾收集可能比堆棧分配更快) - 那麼你不知道什麼時候「變量被釋放」並仍然符合標準。 – 2013-04-28 07:29:48

+1

@BasileStarynkevitch:雖然你的觀點是有效的,並且做得很好,但我不明白它是如何不同意答案中的任何內容的。答案從來沒有說過*實現需要釋放變量*,它只是表示自動和邏輯變量被釋放。從用戶的角度來看,他們是被釋放的。超出範圍的任何用途都是UB。從實施的角度來看,他們可能會也可能不會被釋放,但語言的使用者應該至少不會被這個問題困擾。 – 2013-04-28 07:37:19

+1

我的觀點是「變量被釋放」沒有確切的意義....實現可以自由地做他們想做的事情。從用戶的角度來看,他們沒有被釋放,但已經消失。 – 2013-04-28 07:39:38

1

在回答你的問題時,代碼是否會變得更有效率:很可能不是。一般來說,編譯器會一起收集函數的所有局部變量,並將它們放在外部作用域中。如果他們看到拆分堆棧框架的好理由,那麼他們也會在外部作用域中使用本地代碼。

-1

這裏變量「I」保持它的值,直到控制出來main()函數。

+1

感謝您的回答,但這似乎不是我問題的一部分 – tay10r 2013-04-28 07:55:45