第三十六章 作用域(下)
「被釋放掉了,為了證明這一點,我們在剛才的代碼中添加一句代碼,同時也向你們介紹『&』的第三個功能,取地址。
int fieldArea()
{
int a = 100;
for(int i = 0; i < 10; i++)
{
int b = i;
printf(“b 的地址是:%d“,&b);
}
}
之前我們已經(jīng)學過了『&』的兩種用法,一種是用于兩個數(shù)做位與運算,一種是用來做邏輯與,而這種放在一個變量的命前面的操作,叫做取地址。
至于什么叫地址,我簡單的說一下。
最開始我給你們說過,電腦的最基本組成是成千上萬億個開關構成的,但是雖然都是開關,卻也分不同的類別,主要來說分為三種。
第一種CPU,它是電腦的核心,它的里面的開關狀態(tài)轉換速度非???,但是造價也非常貴,而且里邊的數(shù)據(jù)一斷電就沒了。
第二種硬盤,就是『我的電腦』里邊什么C、D、E、F盤,用來保存文件,代碼這些。硬盤的開關狀態(tài)轉換就很慢了,好處是便宜,里面的數(shù)據(jù)斷了電也不會消失。
當我們要運行程序的時候,CPU需要從硬盤中讀取編譯成機器語言的.exe,但是硬盤的讀寫速度相對于CPU來說太慢了,根本沒有辦法讓它的效率得到有效的發(fā)揮。
于是就引入了第三種——內(nèi)存,內(nèi)存的開關狀態(tài)轉換速度在CPU和硬盤中間,造價也是如此,所以它就作為了CPU和硬盤的一個緩沖介質(zhì)。
內(nèi)存里的數(shù)據(jù)斷電后也會消失,上電后里面是一些隨機值。這就是為什么在聲明變量后,使用之前一定要對它進行初始化的原因了。
當CPU要從硬盤里邊讀寫數(shù)據(jù)的時候,就讓內(nèi)存先去加載,然后CPU再從內(nèi)存中讀取。CPU在讀取內(nèi)存里面的數(shù)據(jù)時,內(nèi)存又可以去硬盤中讀取后面的內(nèi)容,這樣就形成了一個流水線,CPU的執(zhí)行效率就大大提高了。
所以,程序要正常運行,就需要依靠內(nèi)存。一旦內(nèi)存不夠用了,電腦就會變得特別卡,甚至于死機。你們看,桌面邊邊這個顯示百分比的圓球就是電腦管家顯示的內(nèi)存使用情況。
理論上來說,內(nèi)存的容量越大,就可以開越多的程序,但是也不是越大越好。因為程序的執(zhí)行是由CPU來調(diào)度的,假設CPU的極限是調(diào)度1000個程序,而內(nèi)存的容量可以供1500個程序使用也是沒有意義的。
現(xiàn)在主流的配置一般都會給電腦搭配16GB的內(nèi)存,這是什么概念呢?1GByte=1024MByte=1024x1024KByte=1024x1024x1024Byte。在最開始和你們說過,為了方便管理,8個開關被統(tǒng)一為一個字節(jié)(Byte),你們自己算算,這是有多少個字節(jié)。
為了便于管理,開發(fā)計算機的那些科學家就給每一個字節(jié)編了一個號,而這個編號就叫內(nèi)存地址。我們用『&』獲取的正是一個變量在內(nèi)存中的地址?!?p> 老爹一邊說,還一邊將我的電腦機箱蓋子打開了,和我們介紹CPU、內(nèi)存條和硬盤長什么樣子。這些知識雖然看上去和編程沒有關系,但是卻在編程中起著舉足輕重的作用。
老爹在介紹完了之后,我和小弦子將fieldArea函數(shù)給運行了一下,結果讓我傻眼了,因為10次打印出來變量b的地址居然是一樣的!
我重復了運行了好幾次,雖然每次運行b的地址和上一次的不一樣,但是在這10次循環(huán)中的地址卻是一模一樣。
再三檢查后,我確認不是自己的問題,于是看向了小弦子,看看他那邊是個什么情況。
結果小弦子的情況和我完全相同!這是什么情況?難道是老爹講錯了?
我和小弦子都看出了對方眼里的疑惑,我們同時看向了老爹。
老爹愣了一下,然后在看了我和小弦子程序運行結果后陷入了沉思。
緊接著他在自己電腦上運行了一下,結果也是一樣的。
「對不起,孩子們,這里應該是我講錯了。從我讀大學那個時候就一直以為在for循環(huán)體里面聲明的變量應該是每次都是重新生成的,謝謝你們糾正了這個錯誤?!?p> 說完,老爹鄭重地向我們道了歉。
「有很多事情,一直便是如此不見得都是對的,就算是目見耳聞都不一定是真的,通過這件事你們也應該能夠看出來了。所以啊,我希望你們保持一顆質(zhì)疑、求真的心。
好了,咱們接著講作用域。變量的作用域除了通過大括號來判斷,還有幾種比較特殊的情況:
第一種,for循環(huán)小括號中定義的變量。
for(int i = 0; i < 10; i++)
{
}
這里的變量i它的作用域就是整個for,所以我只能在for結構內(nèi)使用它,一旦脫離for的作用域,它就被釋放了。
第二種,聲明在所有函數(shù)外面的變量。
int global = 100;
int main(int argv, char const* args[])
{
}
int func(void)
{}
這里的global變量它在所有的函數(shù)外面,所以當前.c文件中所有的函數(shù)都可以使用它。
還有一點比較重要的東西:如果一個變量的作用域內(nèi)還有其他的作用域,那么在這個作用域里面也是也是用這個變量的。
舉個例子,區(qū)長的作用域是整個郫都區(qū),而紅光鎮(zhèn)是在郫都區(qū)內(nèi),所以區(qū)長自然可以管理紅光鎮(zhèn)的事務。
這也解釋了為什么global能夠被當前.c文件里的所有函數(shù)使用,因為這些函數(shù)的范圍在global作用域中。
那么剛剛main和add中都存在名為sum的變量問題也解決了,因為這兩個sum根本就在是各種的作用域中聲明的。其實重點是在同一個作用域中聲明同名變量,注意,是聲明,而不是不能有,這點一定要注意!
也就是說下面這種是不行的
void func(void)
{
int a = 10;
int a = 10;
}
而下面兩種是可以的:
void funcA(void)
{
int a = 10;
}
void funcB(void)
{
int b = 10;
}
或者這種也是可以的:
int a = 10;
void funcD(void)
{
int a = 20;
}
一下子和你們說了這么多,估計你們很難理解,不過只要多看看,再結合實際運用,應該就能夠理解了。
簡單的來說,作用域你可以理解為一個變量的地盤,當要用這個變量的時候在這個變量的地盤中,那就沒有問題,如果不在這個變量的地盤中,那就不能使用。
還有就是無論什么時候都不能讓電腦疑惑,就像一個作用域中你如果聲明了兩個名字相同的變量,計算機就懵了,因為它也不知你到底是要使用哪一個?!?p> 老爹補充道。
「那上面最后一種情況計算機難道不會疑惑么?它怎么知道到底使用哪個a呢?」
任煦之秋
這是昨天欠下,晚上還有一更