--- GA: G-RZYLL0RZGV --- ###### tags: `大一程設` `東華大學` `東華大學資管系` `基本程式概念` `資管經驗分享` 變數的存活範圍,如何看 block,不再搞混變數範圍,區域變數與全域變數 === [TOC] ## 前言 在撰寫程式時會需要宣告眾多的變數,實體化眾多的物件,而你在哪裏宣告這些變數與物件是非常重要的,在不同的程式區段(block)內宣告的變數他能夠存活的區域也有不同,以下會來分析變數在各個情況下的存活範圍為何 ## 區域變數 Local Variable ### 變數於函示 function 之中 我們先看一段很常見的程式碼 ```cpp= void swap(int a, int b){ int temp; temp = a; a = b; b = temp; cout << a << endl << b; } int main(){ int a = 5, b = 10; swap(a,b); cout << a << endl << b; } ``` 說明: swap 函式的目標是要將參數內的兩個變數進行交換,要使 a = 10, b = 5 透過上面的程式碼,第六行的輸出會是什麼呢?而第 11 行的輸出又是什麼呢? 第六行會印出 10, 5,而第 11 行會印出 5, 10,想必這個結果可能跟自己想的不同,為什麼第 11 行不是印出 10,5 呢?原因就是因為變數的存活範圍是有被限制的,在 swap 函式中參數 a、b 被傳入之後他們的存活範圍僅限於這個 function 之中,當這個函示執行完畢,這兩個變數即釋放記憶體。 簡單的說,若變數被宣告於函示之中,則變數們在函示執行結束時即宣告終止,釋放記憶體。 因為這個原因,當 swap function 執行完回到第十行之後往下,仍舊會印出 5, 10,我們用一張圖來說明這個過程: ![](https://i.imgur.com/uSZjiPe.jpg) 很顯然的,main function 裡的 a,b 與 swapInt 裡面的 a,b 占用的是不一樣的兩塊記憶體,雖然數值是一樣的,但是存取的記憶體位址是不一樣的哦。 **而這樣參數傳遞的方式即是我們常說的 call-by-value,只傳遞值**。 > 小結論一,在學習程式語言最重要的是知道記憶體的分布狀況,清楚了解你在操縱哪一個記憶體位址。 > 小結論二,一旦遇到變數被宣告,系統就會配置記憶體給他,你要生下一個人,總要給他空間活吧! > 這一部分相信比較難以理解,我錄個影片來說明,[影片請點我](https://youtu.be/8o2w_Ikx6kc) > [name=Orange] 那有沒有可能變數不會釋放記憶體且讓我們操縱同一個記憶體的變數呢? 有的,可以透過 [call-by-reference、call-by-address](https://hackmd.io/s9VWr9AAQ5KsXAWPLNv5wg) 兩種傳遞參數的方式來操作,可以透過超連結去看筆記內容。 ### 變數於迴圈之中 ```cpp= int main(){ for(int i = 1; i <= 10; i++){ cout << "我是" << i << "號\n"; } cout << i; } ``` 很顯然迴圈會印出,我是1號、我是2號...我是10號,然而第五行是印不出東西的,甚至你的程式根本 run 不起來,因為針對第五行他會說我找不到 i 這個變數,所以可以知道 i 這個變數只有在迴圈內可以用,因為我們只有在迴圈內宣告而已。 如果你真的有情況需要重複用到迴圈內的 i 值,可以在迴圈外宣告變數,則這整個區塊都能夠使用這個變數 ```cpp= int main(){ int i = 0; for(i = 1; i <= 10; i++){ cout << "我是" << i << "號\n"; } cout << i; } ``` ## 全域變數 Global Variable 全域變數會於 block 外宣告,且全部的程式區段都可使用。 ```cpp= int a = 10; void print(){ cout << a; } int main(){ cout << a << endl; print(); } ``` 通常會被宣告為全域變數的變數是像圓周率、一天有24小時,這種在世界上固定的數,當然也視你遇到的情況而定,而對於這種在世界上是不變的數,我們可以加上 **const** 關鍵字,加上 const 關鍵字的變數,你在程式的任何地方都不能修改他,const 在英文中我們是採用 constant 這個單字,顧名思義就是常數。 ```cpp= const int hour_a_day = 24; int main(){ hour_a_day = 25; return 0; } ``` 像上面這樣你的程式就會報錯哦,因為 const 變數不能修改。 ## 變數採用優先順序 1. 找自身所屬 block 2. 若第一項中沒有,則往外層 block 找(若找到就 stop) 3. 若第二項沒有,往 global variable 找 ```cpp= int x = 10; int main(){ int y = 5; { /* 大括號包住會視為一個區塊 block,所以第8行的 x * 會印出 20,先從自身所屬的 block 開始找 */ int x = 20; int z = 8; cout << x << endl; } /* * 第 17 行的 x 會印出 10,因為他所屬的 block 裡面只看的到全域變數 x * 第 18 行的 z 會印不出來,因為找不到,沒有被宣告,所以會報錯, * 注意! 只能往外層找,不能往內層,所以他看不到第 9 行的 z * */ cout << x << endl; cout << z << endl; return 0; } ```