首頁 現(xiàn)實(shí)

程序媛養(yǎng)成計(jì)劃

第三十五章 作用域(上)

程序媛養(yǎng)成計(jì)劃 任煦之秋 2059 2020-05-08 21:03:50

  我和小弦子興致沖沖地打開了各自電腦上的編輯器,按照老爹剛才所將的內(nèi)容,依葫蘆畫瓢定義了add函數(shù)。

  「呀!編譯出錯(cuò)了!」

  我確認(rèn)了一遍代碼的書寫應(yīng)該沒有錯(cuò),然后湊近小弦子的屏幕看了看他那邊的情況,沒想到小弦子那邊居然沒有出任何問題,編譯成功了!

  這是怎么回事?

  借住翻譯軟件,我大概弄明白了錯(cuò)誤信息,原來是我定義函數(shù)的地方有誤。

  通過對(duì)比我和小弦子的代碼,我發(fā)現(xiàn)自己定義函數(shù)的位置在main函數(shù)中,而小弦子定義在main函數(shù)之外。

  「在C語言中,一個(gè)函數(shù)是不能定義在另外一個(gè)函數(shù)之內(nèi)的!」

  老爹不著痕跡地看了我的代碼一眼,瞬間就看出了問題所在。

  「原來是這樣!」

  我在心里說了一聲,然后就將代碼剪切粘貼到main函數(shù)后邊,至于為什么是后邊嘛,因?yàn)樾∠易臃旁谇斑叺?,我可不想和他一樣?p>  這回編譯倒是通過了,但是報(bào)了一個(gè)警告信息:「implicit declaration of function 'add'」

  意思是函數(shù)add隱式聲明。

  這讓我一頭霧水,隱式聲明又是個(gè)什么鬼意思?關(guān)鍵是小弦子那邊什么信息都沒有輸出!難道問題出在順序上面?

  我在心中暗自狐疑,因?yàn)楝F(xiàn)在我和小弦子的代碼唯一不同的地方就是定義main函數(shù)和add函數(shù)的位置不一樣。小弦子那邊add函數(shù)定義在main函數(shù)前,而我定義在main函數(shù)后邊。

  為了驗(yàn)證心中的猜想,于是我又將它們的順序調(diào)換了一下,警告信息果然消失了!

  我運(yùn)行了一下,程序得到了預(yù)期的結(jié)果,證明邏輯是沒有問題的。

  接著我又將mian和add順序恢復(fù)到原來的樣子,再次編譯,警告信息果然又出現(xiàn)了。我嘗試著運(yùn)行程序,居然也得到了正確的結(jié)果!

  「剛才我就說了,在使用一個(gè)函數(shù)之前,必須要先聲明它,否則就會(huì)報(bào)『implicit declaration of function 'add'』警告。所以我們?cè)趍ain函數(shù)中使用add函數(shù),就應(yīng)該在main函數(shù)之前聲明add。

  當(dāng)然了,如果在程序中我們壓根就沒有定義這么一個(gè)函數(shù),除了會(huì)有這句警告之外,還會(huì)有一個(gè)錯(cuò)誤:『undefined reference to 'add'』」

  我試了一下,果真如同老爹所言。

  「那為什么我在main函數(shù)后面聲明add,程序運(yùn)行的結(jié)果依舊是對(duì)的呢?」

  「這個(gè)就是C語言不嚴(yán)謹(jǐn)?shù)牡胤搅?,以后隨著你們逐漸深入了解C語言,會(huì)發(fā)現(xiàn)類似這樣的問題還有很多。所以后來的C++對(duì)這些問題進(jìn)行了修復(fù),整個(gè)體系就更為嚴(yán)謹(jǐn)、標(biāo)準(zhǔn)化。」

  老爹笑了笑。

  「哦,好吧!原來那些開發(fā)C語言的科學(xué)家也會(huì)有bug的時(shí)候?。 ?p>  「當(dāng)然了,我之前都給你說過了,無論是技術(shù)多么牛的程序員,都不可能排著胸脯說自己的程序沒有任何的bug,特別是軟件體系特別龐大的時(shí)候。

  其實(shí)剛剛那個(gè)問題,add也不是不可以放在main函數(shù)后面,如果我們把函數(shù)的聲明和實(shí)現(xiàn)分開的話就行了。

  函數(shù)的定義分為聲明和實(shí)現(xiàn)兩個(gè)過程,你們現(xiàn)在寫的這種形式是將兩個(gè)過程融合在一起了,如果我們把a(bǔ)dd的聲明放在main函數(shù)前邊,定義放在后邊就不會(huì)有警告信息了,就像這個(gè)樣子:

  int add(int a,int b);

  int main(int argc, char const* args[])

  {

  int sum = add(a, b);

  printf(“sum =%d“, d);

  }

  int add(int a,int b)

  {

  int sum = a + b;

  return sum;

  }

  聲明一個(gè)函數(shù),其實(shí)只需要三個(gè)元素:函數(shù)名,參數(shù)列表和返回值,這個(gè)時(shí)候就不用大括號(hào)了,而是用分號(hào)。

  具體的實(shí)現(xiàn)就和我們之前講的內(nèi)容一樣了。

  如果函數(shù)的實(shí)現(xiàn)在調(diào)用在前,其實(shí)是不用聲明的,就像你們現(xiàn)在這種情況。但是不建議這樣做,因?yàn)楫?dāng)函數(shù)調(diào)用關(guān)系比較復(fù)雜的時(shí)候,我們不好調(diào)整實(shí)現(xiàn)順序,所以正規(guī)的做法是在#include之后聲明所有要定義的函數(shù),然后在main函數(shù)之前或者自后逐一實(shí)現(xiàn)?!?p>  我嘗試了一下老爹所說的,警告信息果然消失了。而且我還發(fā)現(xiàn)了一個(gè)比較有趣的東西,那就是如果我只對(duì)函數(shù)進(jìn)行聲明但是不實(shí)現(xiàn)它,這個(gè)時(shí)候編譯器不會(huì)再報(bào)「implicit declaration of function 'add'」警告,只會(huì)有「undefined reference to 'add'」錯(cuò)誤。

  接下來老爹又給我們演示了有參數(shù),沒有返回值、沒有參數(shù),有返回值,沒有參數(shù),也沒有返回值的幾種情況,這樣一來,我們對(duì)函數(shù)的定義就有了初步的認(rèn)識(shí)。

  「既然函數(shù)的定義和調(diào)用已經(jīng)沒有問題了,那么我們接著再來說說之前玥玥提出的問題,在main函數(shù)里邊有個(gè)名為sum的變量,而add里面也有這么一個(gè)變量,按照之前我的說法,變量的名字不能重復(fù)。

  但是程序現(xiàn)在已經(jīng)正常運(yùn)行了,說明是沒有問題的,那是不是意味著我之前說的是錯(cuò)誤的呢?

  其實(shí)這個(gè)說法的確是有問題的,應(yīng)該要加一個(gè)限定條件,在同一個(gè)作用域里面,不能聲明兩個(gè)名稱一樣的變量。因?yàn)楫?dāng)時(shí)的著重點(diǎn)是將標(biāo)識(shí)符起名規(guī)則,如果引入作用域,對(duì)你們來說很難理解。

  至于什么是作用域,我們還是以現(xiàn)實(shí)中的例子來說明。

  你們看哈,咱們現(xiàn)在住這個(gè)地方呢,是在紅光鎮(zhèn)的轄區(qū)里邊,那么紅光鎮(zhèn)只能有一個(gè)鎮(zhèn)長(zhǎng)對(duì)吧?而且紅光鎮(zhèn)里邊的大小事情都?xì)w鎮(zhèn)長(zhǎng)管?!?p>  我和小弦子點(diǎn)了點(diǎn)頭,而后接著聽老爹講道:「那么我們可以說,鎮(zhèn)長(zhǎng)的作用域就是一個(gè)鎮(zhèn),他只能管自己鎮(zhèn)里的事情。

  那紅光鎮(zhèn)是在郫都區(qū)的管轄范圍之內(nèi),而郫都區(qū)又只能有一個(gè)區(qū)長(zhǎng),整個(gè)區(qū)里面的大大小小的事務(wù),都得由區(qū)長(zhǎng)來管,這其中當(dāng)然也包括了紅光鎮(zhèn)。

  變量也一樣,變量也有自己的作用域,而變量的作用域,就是聲明這個(gè)變量所在的大括號(hào)中,例如:

  int fieldArea()

  {

  int a = 100;

  for(int i = 0; i < 10; i++)

  {

  int b = i;

  }

  }

  這里面的變量a是在fieldArea函數(shù)的大括號(hào)中聲明的,它作用域就是fieldArea函數(shù),一旦脫離了這個(gè)范圍就不能再使用了。而變量b是在for循環(huán)的大括號(hào)中的,那么它的作用域就是一次for循環(huán),也就是說每一次for循環(huán)都會(huì)重新聲明一個(gè)變量b?!?p>  「那上一次循環(huán)的變量b到哪兒去了?」

  

按 “鍵盤左鍵←” 返回上一章  按 “鍵盤右鍵→” 進(jìn)入下一章  按 “空格鍵” 向下滾動(dòng)
目錄
目錄
設(shè)置
設(shè)置
書架
加入書架
書頁
返回書頁
指南