計算機概論:C/C++程式設計
|
第6章 模組化的程式設計基礎:函式 |
|
|
授課教師:陳慶瀚 WWW : http://www.miat.ee.isu.edu.tw/cpp E-mail : pierre@isu.edu.tw |
|
6.3 區域變數和全域變數
變數是一種在程式執行過程中暫時存放資料的記憶空間,對應的變數名稱就是指向該空間的識別代號。變數都有其有效範圍(scope),如果是宣告在func1()函式內的變數,則其有效範圍只在該函數內部,離開這個有效範圍─譬如說在別的函式或是呼叫func1()的主程式裡,就不能夠使用這個變數。這些僅存活在函式內部的變數,就稱為區域變數(local variable)。下列範例程式說明這個概念:
/*----------------------------------------------------*/ // 範例程式6-3 // 華氏溫度轉換攝氏溫度 // 陳慶瀚,2001 /*----------------------------------------------------*/ 1:
#include <iostream.h>
2:
// 函式原型宣告
3:
float F2C(float TempF);
4:
void main()
5:
{
6:
float TF;
7:
float TC;
8:
9:
cout << "請輸入華氏溫度: ";
10:
cin >> TF;
11: // 呼叫函式F2C()
12:
TC = F2C(TF);
13:
cout << "\n轉換為攝氏溫度 = ";
14:
cout << TC << endl;
15:
}
16: // 函式定義
17:
float F2C(float TempF)
18:
{
19:
float TempC;
20:
TempC = ((TempF - 32) * 5) / 9;
21:
return TempC;
22:
}
上例中,我們在函式F2C()中第19行宣告一個變數
float TempC;
變數TempC是一個區域變數,它的有效範圍只在函式內部,我們不能在main()函式中使用這個變數,但是我們可以在main()函式宣告一個相同名稱的變數TempC,譬如把第7行的變數名稱TC改為TempC,這兩個TempC變數將個自獨立,個自在不同的函式中分配記憶空間,而不至於產生混淆,因為兩個變數只有在各自的函式中才是有效的。
定義在函式內部的變數就是區域變數,通常我們會把這些變數宣告在函式一開始的位置,但並非一定要放在開始位置不可。譬如我們可以把變數宣告在迴圈或者if-then-else區塊內,由於迴圈或if判斷區塊是函式內的一個程式區塊,所以這個變數的有效範圍將只有在迴圈區塊或if區塊中,也就是該變數是屬於這個區塊的區域變數,離開這個區塊,就算還在同樣的函式裡,也不能使用這個變數。範例程式6-4就可以看到這個實例。
/*----------------------------------------------------*/ // 範例程式6-4(錯誤) // 使用函式交換兩個正整數的變數值 // 陳慶瀚,2001 /*----------------------------------------------------*/ #include <iostream.h> // 函式原型宣告 void exchange(int a, int b); //主程式 void main() { int a,b; cout<<"請輸入兩個正整數a和b : "; cin>>a>>b; cout<<"a = "<<a<<", b = "<<b<<endl; exchange(a,b); //呼叫函式 cout<<"交換後,a = "<<a<<", b = "<<b<<endl; } //函式定義 void exchange(int a, int b) { int temp=a; a=b; b=temp; } 這個程式編譯時正確,但執行結果是錯的,例如我們輸入:
請輸入兩個正整數a和b
: 7 8
a
= 7, b = 8
交換後,a = 7, b = 8
我們呼叫了exchange()函式,但傳進去的兩個整數並沒有交換,為什麼?
因為在函式
void
exchange(int a, int b)
當中,int a, int b這兩個變數是函式exchange()的區域變數,而在主程式main()當中,我們宣告
int
a,b;
這兩個變數是屬於main()函式的區域變數,雖然它們的名稱相同,但是分屬於不同的scope,各自使用不同的記憶體,所以當我們在main()函式中呼叫exchange()函式,我們同時把main()的a和b值複製給exchange()函式的a和b,當exchange()函式執行完其內部指令,回到主程式後,其區域變數的記憶體已被清除,main()的a和b還是維持原來的值,不受exchange()函式內部指令的影響。
如何修改這個程式呢,只要將
void
exchange(int a, int b)
改為
void
exchange(int &a, int &b)
就可以得到正確的答案了。在函式的傳遞參數宣告時,我們使用取址運算子&,代表我們傳遞的是變數的記憶體位址,而不是變數值。因此呼叫函式的時候,它會將main()函式的區域變數a和b的記憶體位址傳入函式,並指定給exchange()函式的區域變數a和b。由於使用的是相同的記憶體位址,因為一旦a和b在exchange()函式中交換,在main()函式的a,b就保留了交換的結果。
正確的範例程式6-4因此修正如下:
/*----------------------------------------------------*/ // 範例程式6-4(正確) // 使用函式交換兩個正整數的變數值 // 陳慶瀚,2001 /*----------------------------------------------------*/ #include <iostream.h> // 函式原型宣告 void exchange(int a, int b); //主程式 void main() { int a,b; cout<<"請輸入兩個正整數a和b : "; cin>>a>>b; cout<<"a = "<<a<<", b = "<<b<<endl; exchange(a,b); //呼叫函式 cout<<"交換後,a = "<<a<<", b = "<<b<<endl; } //函式定義 void exchange(int a, int b) { int temp=a; a=b; b=temp; } 不同於區域變數,如果我們把一個變數宣告在所有的函式之外─包含main()函式,那麼我們就可以在所有的函數內共同使用這個變數,例如我們可以在A函式內部指定一個值給這個變數,而在函式B內部將這個值輸出。這樣的變數就稱為全域變數(global
variable),一旦程式配置了一個全域變數的記憶空間,這個記憶空間在程式執行過程中任何時間位置都將是有效的,不像區域變數只在特定的程式區塊內(如函式區塊、if條件區塊或for迴圈區塊等等)才有效。
初學者剛接觸全域變數,通常會覺得很方便,因為只要宣告一次就可以全程使用。但是有經驗的程式設計者則會相當謹慎的使用全域變數,因為當程式的複雜度增加,我們可能會不小心在某個函式中宣告了一個與全域變數相同的區域變數名稱,那麼在這個函式內,這兩個名稱相同的全域變數和區域變數就會產生混淆,這個區域變數將覆蓋全域變數的有效性,一般而言,雖然我們仍然可以憑藉個人對程式的熟稔度掌握這兩者的使用時機,但如果程式是由不同的設計者分工撰寫或程式開發期間很長,這種混淆將會變得難以掌握,而造成程式無法順利維護和擴充。範例程式6-5就展示了一個全域變數的實例。
/*----------------------------------------------------*/ // 範例程式6-5 // 使用全域變數 // 陳慶瀚,2001 /*----------------------------------------------------*/ #include <iostream.h>
void increment();
// 函式原型宣告
int count=0;
// 宣告一個全域變數
void main()
{
cout << "initial count = " << count
<< "\n";
increment ();
cout << "After increment(), count = "
<< count << "\n";
count=100;
// 重設count為100
cout << "After reset , count = " << count
<< "\n";
}
void increment()
{
count=count+1;
}
|
||
計算機概論:C/C++程式設計 義守大學電機系 陳慶瀚 |