4. 全域性變數、區域性變數和作用域
全域性變數定義在所有的函式體之外,它們在程式開始執行時分配儲存空間,在程式結束時釋放儲存空間,在任何函式中都可以訪問全域性變數。
如果全域性變數和區域性變數重名了會怎麼樣呢?
例3.6.作用域
則第一次呼叫print_time
列印的是全域性變數的值,第二次直接呼叫printf
列印的則是main
函式區域性變數的值。
設想整個原始檔是一張大紙,也就是全域性變數的作用域,而main
函式是蓋在這張大紙上的一張小紙,也就是main
函式區域性變數的作用域。在小紙上用到識別符號hour
和minute
時應該參考小紙上的定義,因為大紙(全域性變數的作用域)被蓋住了,如果在小紙上用到某個識別符號卻沒有找到它的定義,那麼再去翻看下面的大紙上有沒有定義,例如上圖中的變數x
。
區域性變數可以用型別相符的任意表示式來初始化,而全域性變數只能用常量表示式(constant expression)初始化。例如,全域性變數pi
這樣初始化是合法的:
double pi = 3.14 + 0.0016;但這樣初始化是不合法的:
double pi = acos(-1.0);然而區域性變數這樣初始化卻是可以的。程式開始執行時要用適當的值來初始化全域性變數,所以初始值必須儲存在編譯生成的可執行檔案中,因此初始值在編譯時就要計算出來,然而上面第二種initializer的值必須在程式執行時呼叫
acos
函式才能得到,所以不能用來初始化全域性變數。請注意區分編譯時和執行時這兩個概念。為了簡化編譯器的實現,c語言從語法上規定全域性變數只能用常量表示式來初始化,因此下面這種全域性變數初始化是不合法的:
int minute = 360;int hour = minute / 60;雖然在編譯時計算出
hour
的初始值是可能的,但是minute / 60
不是常量表示式,不符合語法規定,所以編譯器不必想辦法去算這個初始值。如果全域性變數在定義時不初始化則初始值是0,如果區域性變數在定義時不初始化則初始值是不確定的。所以,區域性變數在使用之前一定要先賦值,如果基於乙個不確定的值做後續計算肯定會引入bug。
例3.7.驗證區域性變數儲存空間的分配和釋放
#include void foo(void) int main(void)結果是:
134518128 777修改一下
int main(void)結果是:
134518200 hello 0非定義的函式宣告也可以寫在區域性作用域中,例如:
int main(void)這樣宣告的識別符號
print_time
具有區域性作用域,只在main
函式中是有效的函式名,出了main
函式就不存在print_time
這個識別符號了。
雖然在乙個函式體中可以宣告另乙個函式,但不能定義另乙個函式,c語言不允許巢狀定義函式。
Linux C程式設計一站式學習
北京亞嵌教育研究中心 ps ef grep sctp grep全稱是global regular expression print,表示全域性正規表示式.gdb除錯又看一遍。迅速用起 pthread cond timedwait 條件變數是利用執行緒間共享的全域性變數進行同步的一種機制,主要包括兩個...
Linux C程式設計一站式學習 筆記
關於程式的討論裡提到了c語言的可移植,原本不知道為什麼,現在知道,原來是因為各種平台上都有c語言的編譯器,這就好像是一種由於廣泛使用而成為規範的東西一樣,當所有機器上都有你的編譯器的時候,你的可移植性當然強了。之前看v6shell的 就沒明白詞法和語法有什麼差別,這裡講到了詞法就是單詞 token ...
LinuxC程式設計一站式學習 堆疊
本科學習資料結構時實踐比較少,因此最近開始複習,看到 既可以打基礎,又可以順便學習linux的知識。原始 include define max row 5 define max col 5 struct point stack 512 int top 0 int maze 5 5 void push...