首頁 現(xiàn)實

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

第三十五章 作用域(上)

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

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

  「呀!編譯出錯了!」

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

  這是怎么回事?

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

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

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

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

  「原來是這樣!」

  我在心里說了一聲,然后就將代碼剪切粘貼到main函數(shù)后邊,至于為什么是后邊嘛,因為小弦子放在前邊的,我可不想和他一樣。

  這回編譯倒是通過了,但是報了一個警告信息:「implicit declaration of function 'add'」

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  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;

  }

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

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

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

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

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

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

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

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

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

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

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

  int fieldArea()

  {

  int a = 100;

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

  {

  int b = i;

  }

  }

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

  

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