無痛入手 C++:基礎教學7 - 變數範圍

更新於 發佈於 閱讀時間約 6 分鐘

變數宣告的位置會決定它的「可視範圍」任何陳述都只使用所屬範圍內變數,範圍外的變數是"無法看見"的,當然也就無法使用。

這篇會介紹兩種變數範圍常見的判斷方式:
1. 大括號: 宣告在大括號內的變數,只能被大括號內的陳述所使用。
2. 陳述: 宣告在陳述內的變數,只能在該陳述內被使用。

全域變數 (global variable)

宣告在 main 的大括號以外的變數稱為全域變數,顧名思義,程式中的所有陳述都能看見並存取它。如下所示:

#include <iostream>

using namespace std;

int x = 0;

int main() {
cin >> x;
if (!x) {
x = 100;
}
cout << x;
return 0;
}

因為 x 被宣告在 main 外面,因此 main 中的任何陳述都可以存取它。

注意: 寫程式的時候應該要盡量避免使用全域變數,因為在大型軟體中,濫用全域變數會讓程式變得難以分析、容易產生 bug。

區域變數 (local variable)

宣告在大括號內的變數基本上都是區域變數。我們在 main 以及 if、else if、else 以及 switch 都會使用大括號將陳述包起來,在裡面宣告的變數就是區域變數。執行看看下面的程式,看看會發生什麼錯誤:

if (true) {
{int x = 10;}
{cout << x;}
}

由於 int x = 10;cout << x; 屬於不同的範圍,cout "看不見" x,自然就無法將它的值印出來。下面舉幾個正確的寫法:

// case1​
if (true) {
int x = 10;
cout << x;
}

// case2
if (true) {
{
int x = 10;
cout << x;
}
}

// case3
if (true) {
int x = 10;
{ cout << x; }
}

case 1 是一般的寫法,相信大家都可以理解。
case 2 用額外的一組大括號將兩個陳述包在一起,它們仍然在相同的範圍內,所以是正確的。
case 3 的話,雖然 cout << x; 自己被包在額外的大括號內,但它和 int x = 10; 都被包在第一組大括號內,因此也符合「在同一個大括號內」。

宣告在陳述內的變數也是區域變數,如宣告在 if、else if 以及 for 的小括號內:

// true
if (int x = 1) {
cout << x << '\n';
}

for (int i = 0; i < 3; ++i) { }
// can not use i here

第二行的 if 在小括號中宣告且初始化了一個變數 x,在這種情況,電腦會取出 x 的值來當作條件判斷: 因為 x 的值為 1,且非 0 的整數都換被轉換成布林值的真 (true),所以第二行的條件判斷結果為真。
此外, if 的小括號和大括號屬於同一個範圍 (都屬於 if 陳述),所以第三行可以使用第二行所宣告的 x。

第六行的話則是常見的 for 寫法,因為 x 是宣告在小括號內的,所以只有在 for 裡面可以使用,在 for 的小括號或是大括號外使用 i 是不合法的行為。

變數的遮蔽

下列的程式分別在第一行和第三行都宣告了叫做 x 的變數,執行看看。

int x = 1;
if (true) {
int x = 2;
cout << x;
}

程式會印出 2,這是因為當範圍較小的變數宣告和範圍較大的變數宣告出現相同的名稱時,小範圍的宣告會遮蔽大範圍的暄號,也就是說,第三行的宣告遮蔽了第一行的宣告,所以第四行才會印出 2。

下面再舉一個例子:

int x = 1;
if (true) {
int x = 2;
cout << x << '\n';
}
cout << x;

第六行會印出 1,因對第一行跟第六行在相同的範圍內,所以第六行看見的 x 是第一行所宣告的。

小心不要把宣告跟指定運算子 (=) 的效果搞混,如果把第三行改成 x = 2 的話:

int x = 1;
if (true) {
x = 2;
cout << x << '\n';
}
cout << x;

第三行使用的 x 是第一行所宣告的,因為沒有其他更小的範圍有宣告 x。所以第三行把 x 的值改成 2 以後,第四行跟第六行都會印出 2。

下面再舉一個例子:

int x = 1;
if (true) {
int x = 2;
{
x = 3
}
cout << x << '\n';
}
cout << x;

會印出 3 和 1。第七行看到的是第三行宣告的 x,這個 x 在第五行的時候被改成了 3;第九行看到的則是第一行的 x,它的值並沒有被修改,因此第九行印出的還是 1。

注意: 以上的程式只是為了說明變數範圍而設計的。實際上在寫程式的時候,請盡量幫小範圍的變數取另一個名字,不要測試讀程式的人的耐心。


習題

  1. 以下程式會印出什麼結果?
#include <iostream>

using namespace std;

int x = 0;
int main() {
cout << x << '\n';
int x = 1;
if (int x = 2) {
cout << x << '\n';
{
x = 3;
int x = 4;
}
cout << x << '\n';
x = 5;
}
cout << x << '\n';
return 0;
}
avatar-img
3會員
14內容數
程式設計 & 電腦系統 & 系統軟體
留言0
查看全部
avatar-img
發表第一個留言支持創作者!
鏟薯員的窩 的其他內容
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
電腦只做一件事情: 運算。 我們所看到的任何酷酷的應用: 不論是網頁動畫、遊戲特效、甚至是 AI 說的話,全部都 是由電腦的運算結果組合而成的。 首先我們來梳理一下各個名詞之間的關聯: 1. 運算分成兩個部分: 運算子 (運算的名稱,如: 加法) 和運算元 (運算的對象,如: 8)。運算就是對資
<iostream> ​在之前的文章有提到過,<iostream> 是專門處理程式的輸入 (input) 以及輸出 (output) 的函式庫。輸入輸出的對象是以電腦作為主角: 輸入指的是「把資料給電腦」,輸出指的是「從電腦那邊取得資料」。 在這個系列的文章中,程式輸入指的都是從鍵盤輸入資料給電
電腦只做一件事情: 運算。 我們所看到的任何酷酷的應用: 不論是網頁動畫、遊戲特效、甚至是 AI 說的話,全部都 是由電腦的運算結果組合而成的。 首先我們來梳理一下各個名詞之間的關聯: 1. 運算分成兩個部分: 運算子 (運算的名稱,如: 加法) 和運算元 (運算的對象,如: 8)。運算就是對資
你可能也想看
Google News 追蹤
Thumbnail
現代社會跟以前不同了,人人都有一支手機,只要打開就可以獲得各種資訊。過去想要辦卡或是開戶就要跑一趟銀行,然而如今科技快速發展之下,金融App無聲無息地進到你生活中。但同樣的,每一家銀行都有自己的App時,我們又該如何選擇呢?(本文係由國泰世華銀行邀約) 今天我會用不同角度帶大家看這款國泰世華CUB
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
就是指變數可以被訪問和使用的範圍,來說一下var、let和const的作用域差異。 var :function example() { console.log(x); // 輸出: undefined 因為變量提升造成的 var x = 5; } 函數作用域或全域作用域 可以重複宣告
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
※ ES6 變數宣告介紹: 在ES6中,推薦使用let和const取代原有的var來宣告變數。 ※ var的特點: 勢力範圍(scope)只有兩種:function、global(全域部分)。 勢力範圍(scope)指的是宣告變數的範圍,能夠被有效的使用的範圍。 可以在宣告變數之前就使用。
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
Thumbnail
完成了Debug.log()的測試,接著還是要跟各位簡單講一下C#的一些規則,之後看程式會(比較)看得懂。 又講到變數? 在Unity中,變數是重要的工具,用來儲存和管理資料。讓開發者能夠靈活調整遊戲的行為和性能,減少代碼的重複性,使得遊戲開發更加高效和簡潔。透過使用變數,開發者可以輕鬆修改資料
Thumbnail
現代社會跟以前不同了,人人都有一支手機,只要打開就可以獲得各種資訊。過去想要辦卡或是開戶就要跑一趟銀行,然而如今科技快速發展之下,金融App無聲無息地進到你生活中。但同樣的,每一家銀行都有自己的App時,我們又該如何選擇呢?(本文係由國泰世華銀行邀約) 今天我會用不同角度帶大家看這款國泰世華CUB
Thumbnail
嘿,大家新年快樂~ 新年大家都在做什麼呢? 跨年夜的我趕工製作某個外包設計案,在工作告一段落時趕上倒數。 然後和兩個小孩過了一個忙亂的元旦。在深夜時刻,看到朋友傳來的解籤網站,興致勃勃熬夜體驗了一下,覺得非常好玩,或許有人玩過了,但還是想寫上來分享紀錄一下~
Thumbnail
這篇內容,將會講解什麼是變數,以及與變數相關的知識。包括變數、資料型態、變數賦值、變數的命名規則、變數的作用區域、變數的可重複性、內建變數。
就是指變數可以被訪問和使用的範圍,來說一下var、let和const的作用域差異。 var :function example() { console.log(x); // 輸出: undefined 因為變量提升造成的 var x = 5; } 函數作用域或全域作用域 可以重複宣告
Thumbnail
在本章節中,我們將學習JavaScript的基本語法,包括如何註解代碼和如何聲明變數。瞭解這些基礎知識對於進一步學習和使用JavaScript來編寫代碼是非常重要的。
※ ES6 變數宣告介紹: 在ES6中,推薦使用let和const取代原有的var來宣告變數。 ※ var的特點: 勢力範圍(scope)只有兩種:function、global(全域部分)。 勢力範圍(scope)指的是宣告變數的範圍,能夠被有效的使用的範圍。 可以在宣告變數之前就使用。
前言: 雖然前面有些定義還沒有完整的解釋,但還是後面再說吧, 誰想一直看理論啊(摔本子)
Thumbnail
完成了Debug.log()的測試,接著還是要跟各位簡單講一下C#的一些規則,之後看程式會(比較)看得懂。 又講到變數? 在Unity中,變數是重要的工具,用來儲存和管理資料。讓開發者能夠靈活調整遊戲的行為和性能,減少代碼的重複性,使得遊戲開發更加高效和簡潔。透過使用變數,開發者可以輕鬆修改資料