更新於 2024/05/12閱讀時間約 6 分鐘

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

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

這篇會介紹兩種變數範圍常見的判斷方式:
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;
}
分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.