在C語言程序開發中,我們常常使用一些庫函數(例如printf,sin等函數)。事實上,實際需求通常是非常復雜的,只依靠現有的函數很難完成。這就需要自己定義C語言函數。
可以把一個函數看作是一塊積木,各種各樣的積木才能堆積成復雜的建筑。只有幾種積木,能完成的建筑太有限了,如果能夠自己造各種各樣的積木,再復雜的建筑也能完成。
C語言函數的結構是固定的
在我之前的文章里介紹過,C語言作為編程語言,是一種形式語言,具有固定的格式結構和符號:
返回值類型函數名(參數列表)
{
語句列表
}
注意函數名在相應可見域內要保持唯一性,例如,在main函數所在文件里定義的函數名不能也為main。再啰嗦一下main函數,主要是因為它是默認的入口函數,比較特殊。
- OldStyleC的風格的main函數定義寫成main(){…}形式,不寫返回值類型也不寫參數列表。
- OldStyleC規定不寫返回值類型就表示返回int型,不寫參數列表就表示參數類型和個數沒有明確指出。這種寬松的規定會導致很多復雜的Bug產生,現在的C也保持了這種寫法的兼容,但是鑒于它可能會產生bug,還是不要這樣寫。
- 其實系統在調用main函數時是傳參數的,所以main函數最標準的形式應該是intmain(intargc,char*argv[]),這種參數傳遞在linux下使用起來非常方便,以后用到了再詳細解釋。
- C標準也規定了intmain(void)這種形式,如果不使用系統傳進來的兩個參數也可以寫成這種形式。但除了這兩種形式之外,以其它形式定義main函數都是錯誤的或不可移植的。
自定義函數
在了解了自定義函數的一些限制后,很容易就可以寫出如下代碼。下面的代碼中,我們定義了printA函數,它的參數為空,也沒有返回值,僅僅是打印出一個字母“A”。
我們在codeblocks里執行它,發現程序在控制臺中打印出了字母A。
關于codeblocks的安裝和使用,可點擊我的主頁,查看相關文章。
以后如果想打印A,只需要執行printA函數就可以了。更進一步的,我們自己定義的printA函數也可以當做系統函數(例如)一樣嵌套使用,請看如下代碼:
我們又新定義了一個函數print2A,它的功能就是在控制臺打印兩個A。在codeblocks里執行,發現與預期一致。
體會
從上面的簡單例子中,可以總結出以下信息:
- 同一個函數可以調用多次。
- 可以用一個函數去調用另一個函數,第二個函數可以去調用第三個函數。
- 調用自定義的函數,是通過我們取的名字調用的,例如main函數中調用print2A();
- 函數可以使代碼更簡潔,原本打印兩個A需要兩行代碼,現在只需要print2A一行就可以了。
你可能會說,我定義print2A就用了5行啊,哪里簡潔了。可是,以后只要遇到需要打印兩個A的地方,我都可以調用print2A,如果有10個地方需要打印兩個A呢?另外,如果有一天,我想在打印兩個A的時候不換行,那我只需要修改printA,把里面的“\n”刪掉就可以了,而不用去找那10個需要打印兩個A的地方逐個修改。
讀代碼和讀文章不一樣,按從上到下從左到右的順序讀代碼未必是最好的。比如上面的例子,按順序應該是先看printA再看print2A再看main。不過,如果換一個角度,按代碼的執行順序來讀也許會更好:
因為main是入口函數,所以第一句要執行的就是print2A函數,那它是什么功能呢?于是目光移到print2A函數,它的第一句是printA函數,于是進入printA函數。奧,知道了print2A先要打印一個A,然后又要執行printA函數,又打印了一個A。這下知道了,main函數里的第一句要打印兩個A。
實際上,在很多大型項目中,要熟悉它的代碼結構,第一件事往往就是找到入口函數。
歡迎在評論區一起討論,質疑。文章都是手打原創,每天最淺顯的介紹C語言、linux等嵌入式開發,喜歡我的文章就關注一波吧,可以看到最新更新和之前的文章哦。