C語言 - 第二十七章 | 函式入門 - 變數、函式可視範圍(static 與 extern)
C
中,談到可視範圍(scope
)可分為許多層次,也可以談到很複雜。
- 全域變數(
Global variable
) - 區域變數(
Local variable
) - 區塊變數(
Block variable
)
全域變數(Global variable
)
全域變數是指直接宣告在(主)函式之外的變數,這個變數在整個程式之中都「看」得它的存在,而可以呼叫使用。
1 | const double PI = 3.14159; |
如上例子中,PI
這個變數可以被主函式main()
與函式area()
來使用,通常全域變數是用來定義一些常數,初學者不應為了方便而將所有的變數都設定為全域變數,否則將來一定會發生變數名稱管理上的問題,全域變數的生命週期始於程式開始之時,終止於程式結束之時。
區域變數(Local variable
)
區域變數是指宣告在函式之內的變數,或是宣告在參數列之前的變數,它的可視範圍只在宣告它的函式區塊之中,其它的函式不可以使用該變數,例如在上例的主函式中,你不可以直接對area()
函式中的變數r
進行存取,區域變數的生命週期開始於函式被呼叫之後,終止於函式執行完畢之時。
區塊變數是指宣告在某個陳述區塊之中的變數,例如while
迴圈區塊中,或是for
迴圈區塊,例如下面的變數i
在迴圈結束之後,就會自動消失。
1 | while(...) { |
當可視範圍大的變數與可視範圍小的變數發生同名狀況時,可視範圍小的變數會暫時覆蓋可視範圍大的變數,稱之為「變數覆蓋」。
1 | int num = 10; |
這個程式最後顯示的num
值仍是10
,當執行迴圈時,迴圈內的num
變數作用將覆蓋迴圈外的num
變數;同樣的作用發生於全域變數與區域變數發生同名的時候。
static
當變數有宣告時加上static
限定時,一但變數生成,它就會一直存在記憶體之中,即使函式執行完畢,變數也不會消失。
1 |
|
1 | // 執行結果 |
雖然變數c
是在count()
函式中宣告的,但是函式結束後,變數仍然存在,它會直到程式執行結束時才消失,雖然變數一直存在,但由於它是被宣告在函式之中,所以函式之外仍無法存取static
變數。
這邊為了讓大家更了解上方案例的static
,這邊做了一點比照。
而宣告全域static
變數,其在程式執行期間一直存在,但在一個原始程式文件中宣告全域static
變數,還表示其可以存取的範圍僅限於該原始程式文件之中,也可以將函式宣告為static
。
1 | static void some() { |
一個static
函式表示,其可以呼叫的範圍限於該原始碼文件之中,如果有些函式僅想在該原始程式文件之中使用,則可以宣告為 static
,這也可以避免與其他人寫的函式名稱衝突的問題。
extern
extern
可以聲明變數會在其他的位置被定義,這個位置可能是在同一份文件之中,或是在其他文件之中。
1 | // some.c |
1 | // main.c |
若使用gcc some.c main.c
進行編譯,在main.c
中實際上並沒有宣告some_var
,extern
指出some_var
是在其他位置被定義,編譯器會試圖在其它位置或文件中找出some_var
的定義,結果在some.c
中找到,因而會顯示結果為1000.000000
。
要注意的是,extern
聲明some_var
在其他位置被定義,如果在使用extern
時同時指定其值,則視為在該位置定義變數,結果就引發重覆定義錯誤。
1 | // 錯誤 |
1 | // 正確 |
當static
與extern
與inline
一同使用時,情況會複雜一些,詳情可參考(Inline Functions In C)[http://www.greenend.org.uk/rjk/tech/inline.html]。
註:以上參考了
變數、函式可視範圍(static 與 extern)