在前面課程,談的變數主要在主程式main()的大刮號 {...} 裡來宣告變數,
學到函式這邊的程式結構後,或許有同學會發現,
變數會因為在宣告、和使用的位置上,
會有所差別...
這其中有幾種狀態,說明如下:
- 全域變數(global variable):
宣告位置在程式(函式、主程式main)以外的變數,
此類的變數在所有函式、主程式main中,都能存取使用,
變數的作用範圍(scope)、或稱生命週期、或視域,
是從執行程式開始,到程式結束才終止。
範例1a:全域變數
#include <stdio.h>
#include <stdlib.h>
int a; //宣告全域變數a
void func() {
a=7;
}
main()
{
int b=2, c=3;
a = b+c;
func();
printf("a=%d\n", a);
system("PAUSE");
return 0;
}
請執行上述程式,並記錄結果。
說明:變數a,宣告於函式func、main的{ }外部,在main中經運算後a為5,
但之後呼叫func,在func更改a為7;
由於是全域變數,所以a變數的更改,都可以保持紀錄。
範例1b(此a非彼a):
#include <stdio.h>
#include <stdlib.h>
int a; //宣告全域變數a
void func() {
a=7;
}
main()
{
int a;
int b=2, c=3;
a = b+c;
func();
printf("a=%d\n", a);
system("PAUSE");
return 0;
}
如果在主程式main中,也宣告一個變數a,請執行並觀察結果會如何?
說明:在main()裡,會以宣告的a變數作為main的a變數,
而不是用main外面宣告的a變數;
簡單來看,如果區域{...}內。有宣告的同名變數,
會優先以範圍小的變數來使用。
- 區域變數(local variable):
在函式/副程式中宣告的變數,或在參數列宣告的變數;
該類的變數,只能在該函式內能存取使用,
無法讓其他函式、或主程式main()內來存取使用。
範例2a:區域變數 (函式內的a)func_var02a.c
#include <stdio.h>
#include <stdlib.h>
void func()
{
int a;
a=1;
}
main()
{
int a=5;
func();
printf("main a=%d\n",
a);
system("PAUSE");
return 0;
}
請執行上述程式,並記錄結果。
說明:在main裡的 a變數,初始設定為5,之後呼叫func(),
因函式func裡也有宣告a變數,此a為區域變數,一旦離開函式則作用範圍消失;
所以,當main繼續執行下去,其中的a變數,則仍是前面的a (非函式中的a)。
範例2b: 靜態變數func_var02b.c
#include <stdio.h>
#include <stdlib.h>
void counter()
{
static int a=1;
printf("counter:a=%d\n", a);
a=a+1;
}
main()
{
//a=10;
counter();
counter();
system("PAUSE");
return 0;
}
a.執行上述程式,看看執行結果。
b.去掉static,重編執行,比較結果為何?
static 修飾詞是靜態的意思,
作用是讓宣告的變數生命週期,在該檔案的程式執行結束前,都能存在。
但只能在該函式中修改、改變此變數的值,
(也就是需要透過呼叫該函式執行修改,不能在主程式直接設定改變)。
上述呼叫兩次counter,所以a值會累積.
範例2c: 靜態變數func_var03.c
#include <stdio.h>
#include <stdlib.h>
void swap(int x, int y)
{
int tmp;
tmp = x;
x = y;
y = tmp;
//printf("swapfunc: x=%d y=%d\n", x, y);
}
main()
{
int x=2, y=3;
swap(x, y);
printf("x=%d y=%d\n", x, y);
system("PAUSE");
return 0;
}
a.執行上述程式,看看執行結果。
b.把swap裡的註解去掉,再看看結果為何?
c.為什麼會這樣呢?
- 區塊變數(block variable)(C++):
此類變數宣告在結構如 for、while等的區塊{ }內,
當離開該語法大刮號{ }區塊,則會終止不能使用。
C語言裡,是沒有這種(name space)的定義,
在一些gcc編譯器下,在for裡宣告變數會出現錯誤;
但在C++裡是有支援這樣的用法,會以大刮號刮住範圍為一個name space。
PS: scope範圍小的變數、會暫時取代scope範圍大的變數值
範例:func_var04.cpp (副檔名請存.cpp)
#include <stdio.h>
#include <stdlib.h>
main()
{
int i=10;
for(int i=0; i<=15; i++) {
printf("inner i=%d\n",
i);
}
printf("outer i=%d\n",
i);
system("PAUSE");
return 0;
}
執行上述程式,觀察outer i的結果。
- 外部變數extern:
當在檔案中宣告extern變數時,編譯器會在連結的檔案內尋找這名稱的外部變數名,
如果有,則拿來使用,若無,則會有錯誤訊息!
檔案: test1.c
#include <stdio.h>
#include <stdlib.h>
main()
{
extern int var_a;
//呼叫外部檔案的變數
printf("var_a=%d\n", var_a);
system("PAUSE");
return 0;
}
檔案: test2.c
int var_a=2022;
注意:若在Dev C下要執行,需以開啟專案(Project)的模式方式(副檔名.dev),
在開啟新專案後,選擇「Console Application」,
然後在專案下,以「新增檔案」或「將檔案加入專案」選項,
將上述兩個檔案加入,以一般執行方式去編譯執行即可。
- const 唯讀變數:
const 常數變數,此修飾詞使用在變數上時,會讓此變數在其作用範圍scope內,都不能被更改。
意思是此變數只能讀取(唯讀)。
例1:
const float pi=3.1415;
說明:宣告定義浮點數 pi=3.1415為靜態常數,且在程式中不能變更pi.
但在指標變數作用下,不同位置會有不一樣的效果;
例2: a指標指向一個const整數,意思是不能透過指標a去更改c的值.
int c=5;
const int* a=&c;
例3: a是一個const整數指標, 指向c,無法更改a這個指標變數.
int c=5;
int* const a=&c;
練習 func_var05.c:
#include <stdio.h>
#include <stdlib.h>
void test1() {
int c=5, d=6;
const int* a=&c; //讓指標不能改變「指向位址的值」.
//*a=7; // <-錯誤
a=&d; // 但可以改變指標變數的值
printf("a=%d\n", *a);
}
void test2() {
int c=5, d=6;
int* const a=&c; //讓指標變數不能改變「目前指向的位址」.
*a=7; // 但可改變指標變數指向位址的值.
//a=&d; // <-錯誤
printf("a=%d\n", *a);
}
main()
{
test1();
test2();
system("PAUSE");
return 0;
}
執行比較 test1(), test2()的結果。
- register 變數:
register此修飾詞,原本是暫存器的意思,
早期的電腦,其暫存器的處理速度遠比記憶體來的快,
所以,當初的設計是讓編譯器將有此宣告的變數,放入暫存器內加速執行的處理;
但隨著編譯技術的優化,及暫存器資源的配置逐漸讓給OS控管,
這樣的資源會由作業系統端來配置,不一定真的能使用到,逐漸意義式微了。
- 紙筆算算看:
|
|