《Linux C一站式學習》第三章 簡單的函式

2021-08-26 11:22:46 字數 1642 閱讀 3065

4. 全域性變數、區域性變數和作用域

全域性變數定義在所有的函式體之外,它們在程式開始執行時分配儲存空間,在程式結束時釋放儲存空間,在任何函式中都可以訪問全域性變數。

如果全域性變數和區域性變數重名了會怎麼樣呢?

例3.6.作用域

則第一次呼叫print_time列印的是全域性變數的值,第二次直接呼叫printf列印的則是main函式區域性變數的值。

設想整個原始檔是一張大紙,也就是全域性變數的作用域,而main函式是蓋在這張大紙上的一張小紙,也就是main函式區域性變數的作用域。在小紙上用到識別符號hourminute時應該參考小紙上的定義,因為大紙(全域性變數的作用域)被蓋住了,如果在小紙上用到某個識別符號卻沒有找到它的定義,那麼再去翻看下面的大紙上有沒有定義,例如上圖中的變數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...