你知道C語言中函數調用和嵌套嗎?函數必學模塊,你不得不知!

2021-01-07 騰訊網

一、函數調用

什麼是函數調用呢?通常在C語言中,一個完整的項目程序是不可能在一個函數中實現所有的功能。而是由若干功能不同的函數來實現,並且函數之間會存在互相調用的情況。

當然了,也不是說就一定要把函數的功能模塊都分開來寫,但是如果你寫成了下面這個樣子:

我估計以後你的項目經理肯定會對你好(ba)言(dao)相(xiang)勸(xiang)的。

二、函數的調用方式

函數是C語言的基本組成元素,如果你要想實現函數的功能,那麼你就必須學會正確調用函數。調用的語法格式如下:

從上面的語法格式可以看出,當我們調用一個函數時,需要明確函數名和實參列表。實參列表中的參數可以是常量、變量、表達式或者空,並且各參數之間要使用英文逗號分隔開來。

根據函數在程序中出現的位置,有下列三種函數調用方式:

1、將函數作為表達式調用

將函數作為表達式調用時,函數的返回值參與表達式的運算,此時要求函數必須有返回值。示例代碼如下所示:

2、將函數作為語句調用

函數以語句的形式出現時,可以將函數作為一條語句進行調用。示例代碼如下所示:

3、將函數作為實參調用

將函數作為另一個函數的實參時,要求該函數有返回值。示例代碼如下所示:

在上面的語句中,將函數max()的返回值作為printf()函數的實參來使用。

三、嵌套調用

在C語言中,函數的定義是獨立的,也就是說,一個函數不能定義在另一個函數內部。

但在調用函數時,可以在一個函數中調用另一個函數,這就是函數的嵌套調用。接下來我們通過一個案例來演示函數的嵌套調用。

案例一:

運行結果:

在這個案例中,main()函數中調用了 max4()函數,max4()函數中又調用了max2()函數。

為了讓大家能夠更好地理解這個程序執行的流程,我們通過一張圖來描述:

這張圖展示了程序中含有三層函數調用嵌套的情形,總共分為9個步驟,具體如下:

(1) 執行main()函數的開頭部分;

(2) 遇到函數調用語句,調用max4()函數,流程轉向max4()函數入口;

(3) 執行max4()函數的開頭部分;

(4) 遇到函數調用語句,調用max2()函數,流程轉向max2()函數入口;

(5) 執行max2()函數,如果再無其他嵌套的函數,則完成max2()函數的全部操作;

(6) 返回到max2()函數中調用max4函數的位置;

(7) 繼續執行max4()函數中尚未執行的部分,直到max4()函數結束;

(8) 返回main()函數中調用max4()函數的位置;

(9) 繼續執行main()函數的剩餘部分直到結束。

& 多學一招:函數調用時最多可以嵌套多少層?

大家肯定會問:「既然函數嵌套調用和普通的調用看上去沒什麼區別,那是不是可以進行無限層的函數嵌套調用呢?」

很遺憾,函數可以嵌套調用多少層是由程序運行時一個名為「棧」的數據結構決定的。

一般而言,Windows上程序的默認棧大小大約為8KB,每一次函數調用至少佔用8個字節,因此粗略計算下,函數調用只能嵌套大約一千層,如果嵌套調用的函數裡包含許多變量和參數,實際值要遠遠小於這個數目。

當然,單純手動書寫代碼寫出一千層嵌套函數調用基本是不可能的,但是一種名為「遞歸」的方法可以輕鬆達到這個上限。

四、遞歸調用

在數學運算中,會遇到計算多個連續自然數之間的和的情況。

例如要計算1~n之間自然數之和,就需要先計算1加2的結果,用這個結果加3再得到一個結果,用新得到的結果加4,以此類推,直到用1~(n-1)之間所有數的和加n。

在程序開發中,要想完成上述功能,就需要使用函數的遞歸調用,所謂的遞歸調用就是函數內部調用自身的過程。

需要注意的是,遞歸必須要求有結束條件,不然就會陷入無限遞歸的狀態,永遠無法結束調用。接下來通過一個計算自然數之和的案例來學習遞歸調用。

案例二:

運行結果:

案例二中,我們定義了一個getsum()函數用於計算1~n之間自然數之和。

案例中的第9行代碼相當於在getsum()函數的內部調用了自身,這就是函數的遞歸,整個遞歸過程在n==1時結束。

由於函數的遞歸調用過程很複雜,接下來通過一個圖例來分析整個調用過程。

這張圖中描述了遞歸調用的過程,整個遞歸過程中getsum()函數被調用了4次,每次調用時,n的值都會遞減。

當n的值為1時,所有遞歸調用的函數都會以相反的順序相繼結束,所有的返回值會進行累加,最終得到的結果為10。

相關焦點

  • Python使用ctypes模塊調用DLL函數之C語言數組與numpy數組傳遞
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了
  • 每天都在調用函數,Go 中函數調用的原理你知道嗎?
    函數是 Go 語言中的一等公民,理解和掌握函數的調用過程是深入學習 Golang 時無法跳過的步驟,這裡會介紹 Go 語言中函數調用的過程和實現原理並與 C 語言中函數執行的過程進行對比,同時對參數傳遞的原理進行剖析,讓讀者能夠清楚地知道 Go 在函數的執行過程中究竟都做了哪些工作。
  • 使用C++調用python3模塊中的類/函數詳細經驗
    二、測試環境是否成功搭建C++初始化python環境示例函數:// test.cpp 中的初始化函數int init_env(char* mode){ printf("init python env\n"); // 設置python路徑 替換為你自己的python環境/虛擬環境的路徑 Py_SetPath
  • C語言函數指針之回調函數
    如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發生時由另外的一方調用的,用於對該事件或條件進行響應。2 為什麼要用回調函數?
  • C語言函數調用過程中的內存變化解析
    局部變量的作用域為什麼僅限於函數內?這個調用不是指C 語言上的函數調用的語法,而是在內存的視角下,函數的調用過程。本文將從C 語言調用實例,內存視角,反彙編代碼來探討C 語言函數的調用過程,也可以說是C 語言函數調用過程圖解。通過這個C 語言函數調用過程圖解,同學們將會知道,C 語言函數在調用時,內存空間是怎樣變化的。 要想理解這一個過程還好涉及到函數棧幀的概念。
  • C語言函數的調用 - 百度經驗
    在一個程序的編寫過程中,隨著代碼量的增加,如果把所有的語句都寫到 main 函數中,一方面程序會顯得的比較亂,另外一個方面,當同一個功能需要在不同地方執行時,我們就得再重複寫一遍相同的語句。此時,如果把一些零碎的功能單獨 寫成一個函數,在需要它們時只需進行一些簡單的函數調用,這樣既有助於程序結構的清晰條理,又可以避免大塊的代碼重複。
  • 傳智播客:C語言函數對另外一個源文件函數進行調用(外部函數)
    當一個程序由多個源文件組成的時候,根據函數是否能被其他源文件調用的時候,將函數分為內部函數和外部函數,本文就會圍著這外部函數的特點進行講解,希望每一個在學C語言的小夥伴都能弄懂函數的知識點。那麼在C語言當中,可以被其他源文件調用的函數成為外部函數,在調用外部函數之前,需要在當前源文件中定義外部函數。
  • 傳智播客:兩張圖看懂C語言當中的嵌套、遞歸調用
    在C語言當中,大家都一致認為函數和指針部分的內容比較,並且是C語言裡面很重要的基本組成元素。一個完整的應用程式是不可能在一個函數裡面實現所有我們想要的功能。通常程序都是由很多的功能而且不同的函數功能來實現。並且在函數之間會存在互相調用的情況。
  • C語言的那些小秘密之函數的調用關係
    顯示函數的調用關係是調試器的必備功能,如果我們在程序的運行中出現了崩潰的情況,通過函數的調用關係可以快速定位問題的根源,懂得函數調用關係的實現原理也可以擴充自己的知識面,在沒有調試器的情況下,我們也可以自己來實現顯示函數的調用關係。
  • Python使用ctypes模塊調用DLL函數之複數數組的參數傳遞
    這兒就涉及到了如何將C語言中的複數數組(Complex array)類型與Python中的數據類型進行交互的問題。在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,前面多篇文章中已經講了傳遞數值/指針/字符串參數、傳遞結構體參數、傳遞普通數組類型的例子,大家可以回看一下,這樣可以更好的理解本次要講的內容。
  • 單片機C語言教程:C51函數
    有了函數C 語言就有了模塊化的優點,一般功能較多的程序,會在編寫程序時把每項單獨的功能分成數個子程序模塊,每個子 程序就能用函數來實現。函數還能被反覆的調用,因此一些常用的函數能做成函數庫以供在編寫程序時直接調用,從而更好的實現模塊化的設計,大大提高編程工作的效率。
  • C語言之函數
    一.函數的概念1.C語言中,最簡單的程序模塊就是函數。2.函數被視為程序設計的基本邏輯單位,一個c程序是由一個main()函數和若干其他函數組成。3.程序執行從main()函數開始,main()函數可以調用其他函數,其他函數可以互相調用。
  • 為何C語言函數調用要堆棧,而彙編卻不需要?
    上下文,英文叫做context,就是上面的文章,和下面的文章,即與你此刻,當前CPU運行有關係的內容,即那些你用到寄存器。所以,和上面的現場,是一個意思。保存寄存器的值,一般用的是push指令,將對應的某些寄存器的值,一個個放到堆棧中,把對應的值壓入到堆棧裡面,即所謂的壓棧。
  • 快速上手系列-C語言之函數
    上篇寫了C語言中的數組,那接下來就到函數了吧。函數是C語言程序的基本模塊,通過對函數模塊的調用實現特定的功能。每個 C 程序都至少有一個函數,那就是主函數 main(),C語言不僅提供極為豐富的庫函數,還允許用戶建立自己定義的函數,就是說所有的C程序都可以定義其他額外的函數。
  • python語言中嵌套的兩種方式
    二、在兩個物體有裝配關係時,將一個物體嵌入另一物體中的方法。我們先來了解第一個意思,由淺入深,循序漸進。在本文中,學記會將兩種嵌套分為同語言和異語言兩種模式來分別解釋著兩種嵌套的方法。while 表達式:while 表達式 :執行語句執行語句函數嵌套函數的嵌套比循環語句的嵌套要複雜一些,所有函數的定義都是互相平行和獨立的
  • python使用ctypes模塊調用DLL函數之傳遞數值、指針與字符串參數
    在Python語言中,可以使用ctypes模塊調用其它如C++語言編寫的動態連結庫DLL文件中的函數,在提高軟體運行效率的同時,也可以充分利用目前市面上各種第三方的DLL庫函數,以擴充Python軟體的功能及應用領域,減少重複編寫代碼、重複造輪子的工作量,這也充分體現了Python語言作為一種膠水語言所特有的優勢。
  • Python嵌套函數:外部函數與內部函數
    在學習條件判斷IF時,我們就知道「嵌套」的概念,而函數也是可以利用嵌套的。即函數內部可以再定義函數,俗稱嵌套函數。從執行結果我們可以看到:內部函數的print語句未被執行,所以我們可以判斷出不論外部還是還是內部函數,都需要被調用才能執行函數體的內容。
  • C語言(新手)kbhit()函數的調用
    #這個函數C語言裡面有很多函數,每個函數都有一些獨特的功能。有些函數功能非常強大還很有趣,了解遊戲函數的功能對編程非常有幫助的。在C語言中我們調用函數都有先聲明一個頭文件。畢竟我是新手嘛,遇見好玩的函數就像分享一下。
  • 傳智播客:C語言當中內部函數調用的方法和代碼格式
    上一篇文章具體講的是外部函數的格式還有運行結果等等...今天和大家分享一下內部函數。內部函數由上一個小節講解的外部函數可以知道,只要聲明一個函數的原型就可以調用其他的源文件中的函數。但是當多個人參與開發一個項目的時候,有很大的可能會出現函數的重名的情況,這樣的話不同源文件的重名的函數就會互相干擾。
  • assert函數-論java中assert函數和Python、PHP、C語言assert函數
    assert函數廣泛在java、Python、PHP、C語言中存在,都有統一的意義,用業界語言稱之為"斷言"。最初的出發點都是為了方便調試而設計的,但是最近越來越多的開發者不分測試環境和正式環境濫用assert函數,引發了我對廣大程式設計師朋友的擔憂,故寫此篇文章普及assert函數常識,避免各位朋友濫用assert函數。簡單的概況在各個語言中assert函數的意義:如果表達式的值為假,整個程序將退出,並輸出一條錯誤信息。如果表達式的值為真則繼續執行後面的語句。