-
1 # IT劉小虎
-
2 # IT劉小虎
在開發C語言程式的過程中,若是能為變數取一個合適的名字,即使不寫額外的註釋也能讓整個程式段一目瞭然。不過遺憾的是,有時候好用的名字會被其他變數佔用,這時為變數取名就是一件頭疼的事了。
我常常在同事的程式碼裡看到諸如 size1, size2, size3 的變數名,令人眼花繚亂。
區域性變數的作用域,是整個函式嗎?總體來說,C語言中的變數可根據作用域的不同分為全域性變數和區域性變數。一般來說,定義在函式中的變數被稱為區域性變數,非 static 區域性變數存在於函式的棧幀中,函式的棧幀在其執行完畢後會被系統回收,此時區域性變數自動釋放,因此區域性變數只在函式中有效。這一點相信即使C語言初學者,也是明白的。
不過不知道讀者有沒有想過這個問題:C語言函式中的區域性變數作用範圍是整個函式嗎?比如,在函式 fun() 中定義了變數 size,那 size 是否在 fun() 函式所屬的整個程式碼段都可用呢?在回答這個問題之前,應明白,至少gcc version 4.8.4 已經不再限制C語言函式定義變數必須在程式碼段的開頭了,也就是說下面這段C語言程式碼是合法的:
定義變數 i 可以在若干行語句之後,甚至像下面的C語言程式碼這樣,在 if 語句塊中定義變數 size 也是合法的,請看:
現在在上面的C語言 main() 函式返回前新增一行 size ++;,即:
編譯並執行新增 size++; 之後的C語言程式碼,會發生什麼呢?請看:
編譯失敗了,提示第 8 行的 size 沒有宣告!這就奇怪了,size 明明在上面的C語言程式碼第 6 行聲明瞭啊?!這其實就解答了“C語言函式中的區域性變數作用範圍是整個函式嗎?”這個問題,顯然,區域性變數 size 的作用範圍就不是整個函式。
不知道會不會有朋友認為:編譯失敗是因為 if 語句沒有執行,所以 int size = 30; 也沒有執行,因此 size 沒有宣告。
既然區域性變數作用域不是整個函式,那它的作用域是什麼呢?相信讀者已經知道,C語言程式碼中具有人類語言意義的 main、if、while 等詞只是為了便於程式設計師使用,計算機並不能識別這些單詞,因此若想執行C語言程式,需要透過編譯器將程式碼“翻譯”成計算機認識的指令序列。
編譯器在編譯C語言程式碼過程中,也要處理變數的作用範圍問題。應明白“全域性”和“區域性”是對相對概念,所以編譯器首先需要定義一個“區域性”的標準,將“{}”符號包圍的程式碼視為一個“區域性”就是一個不錯的選擇。
以上分析基於 gcc version 4.8.4。
現在就清楚了,區域性變數的作用範圍就是它所屬的 “{}” 包圍的程式碼塊,而全域性變數的作用範圍則是多個 “{}” 包圍的程式碼塊。再來看上面的問題,main() 函式中第 6 行的 size 屬於 if{} 程式碼塊,而第 8 行的 size 屬於 main{} 程式碼塊,因此雖然它倆名字一模一樣,但是編譯器仍然會認為是不同的變數,編譯就報錯了。
事實上,在C語言程式開發中,可以只使用“{}”做區域性處理,例如下面這段程式碼:
編譯上面這段C語言程式碼並執行,結果如下:
顯然,函式內部的 “{}” 包裹的C語言程式碼段並沒有影響到外面的 size,這下就不用怕變數名被佔用了。
函式內部子{}程式碼塊執行完畢之後,變數記憶體會被釋放嗎?這個問題的答案其實上面已經解釋了,變數即使是函式內部子{}程式碼塊裡的區域性變數,它也是儲存在函式的棧幀內的,而棧幀只有在整個函式執行完畢後才會被系統回收,所以函式內部子{}程式碼塊裡的區域性變數佔用的記憶體也在函式執行完畢之後才會被釋放。
可以做如下實驗,首先在函式的子 {} 程式碼塊外部定義一個很大的陣列,相關C語言程式碼如下,請看:
編譯並執行這段C語言程式碼,然後使用 top 命令檢視程式所佔資源如下:
編譯並執行這段C語言程式碼,然後使用 top 命令檢視程式所佔資源如下:
已經一目瞭然了。
小結C語言函式中的區域性變數的作用範圍有時並不是整個函式,利用這一點可以在一定程度上解決變數名被佔用的問題。不過應該注意,函式內部子{}程式碼塊裡的區域性變數佔用的記憶體也在函式執行完畢之後才會被釋放。
回覆列表
在開發C語言程式的過程中,若是能為變數取一個合適的名字,即使不寫額外的註釋也能讓整個程式段一目瞭然。不過遺憾的是,有時候好用的名字會被其他變數佔用,這時為變數取名就是一件頭疼的事了。
我常常在同事的程式碼裡看到諸如 size1, size2, size3 的變數名,令人眼花繚亂。
區域性變數的作用域,是整個函式嗎?總體來說,C語言中的變數可根據作用域的不同分為全域性變數和區域性變數。一般來說,定義在函式中的變數被稱為區域性變數,非 static 區域性變數存在於函式的棧幀中,函式的棧幀在其執行完畢後會被系統回收,此時區域性變數自動釋放,因此區域性變數只在函式中有效。這一點相信即使C語言初學者,也是明白的。
不過不知道讀者有沒有想過這個問題:C語言函式中的區域性變數作用範圍是整個函式嗎?比如,在函式 fun() 中定義了變數 size,那 size 是否在 fun() 函式所屬的整個程式碼段都可用呢?在回答這個問題之前,應明白,至少gcc version 4.8.4 已經不再限制C語言函式定義變數必須在程式碼段的開頭了,也就是說下面這段C語言程式碼是合法的:
定義變數 i 可以在若干行語句之後,甚至像下面的C語言程式碼這樣,在 if 語句塊中定義變數 size 也是合法的,請看:
現在在上面的C語言 main() 函式返回前新增一行 size ++;,即:
編譯並執行新增 size++; 之後的C語言程式碼,會發生什麼呢?請看:
編譯失敗了,提示第 8 行的 size 沒有宣告!這就奇怪了,size 明明在上面的C語言程式碼第 6 行聲明瞭啊?!這其實就解答了“C語言函式中的區域性變數作用範圍是整個函式嗎?”這個問題,顯然,區域性變數 size 的作用範圍就不是整個函式。
不知道會不會有朋友認為:編譯失敗是因為 if 語句沒有執行,所以 int size = 30; 也沒有執行,因此 size 沒有宣告。
既然區域性變數作用域不是整個函式,那它的作用域是什麼呢?相信讀者已經知道,C語言程式碼中具有人類語言意義的 main、if、while 等詞只是為了便於程式設計師使用,計算機並不能識別這些單詞,因此若想執行C語言程式,需要透過編譯器將程式碼“翻譯”成計算機認識的指令序列。
編譯器在編譯C語言程式碼過程中,也要處理變數的作用範圍問題。應明白“全域性”和“區域性”是對相對概念,所以編譯器首先需要定義一個“區域性”的標準,將“{}”符號包圍的程式碼視為一個“區域性”就是一個不錯的選擇。
以上分析基於 gcc version 4.8.4。
現在就清楚了,區域性變數的作用範圍就是它所屬的 “{}” 包圍的程式碼塊,而全域性變數的作用範圍則是多個 “{}” 包圍的程式碼塊。再來看上面的問題,main() 函式中第 6 行的 size 屬於 if{} 程式碼塊,而第 8 行的 size 屬於 main{} 程式碼塊,因此雖然它倆名字一模一樣,但是編譯器仍然會認為是不同的變數,編譯就報錯了。
事實上,在C語言程式開發中,可以只使用“{}”做區域性處理,例如下面這段程式碼:
編譯上面這段C語言程式碼並執行,結果如下:
顯然,函式內部的 “{}” 包裹的C語言程式碼段並沒有影響到外面的 size,這下就不用怕變數名被佔用了。
函式內部子{}程式碼塊執行完畢之後,變數記憶體會被釋放嗎?這個問題的答案其實上面已經解釋了,變數即使是函式內部子{}程式碼塊裡的區域性變數,它也是儲存在函式的棧幀內的,而棧幀只有在整個函式執行完畢後才會被系統回收,所以函式內部子{}程式碼塊裡的區域性變數佔用的記憶體也在函式執行完畢之後才會被釋放。
可以做如下實驗,首先在函式的子 {} 程式碼塊外部定義一個很大的陣列,相關C語言程式碼如下,請看:
編譯並執行這段C語言程式碼,然後使用 top 命令檢視程式所佔資源如下:
編譯並執行這段C語言程式碼,然後使用 top 命令檢視程式所佔資源如下:
已經一目瞭然了。
小結C語言函式中的區域性變數的作用範圍有時並不是整個函式,利用這一點可以在一定程度上解決變數名被佔用的問題。不過應該注意,函式內部子{}程式碼塊裡的區域性變數佔用的記憶體也在函式執行完畢之後才會被釋放。