言C語言陷阱與技巧第21節,函數只能返回一個值嗎?有多個返回值怎麼...

2020-12-06 IT劉小虎

如今幾乎找不到只專注於一門程式語言的程式設計師了。大多數程式設計師在自己平時的工作和生活中,一般都使用不止一門程式語言,例如小編在工作中主要使用的是C語言,但是有時候驗證算法也會使用 matlab 和 python,在業餘做別的項目時還會用到 C#。

不得不承認,就便用性而言,C語言的確相對比較簡陋,所以如果從C語言轉向別的程式語言還好,要是從 python 這樣的高級語言轉向 C語言,常常會感到一些「不便」。例如使用 python 編寫程序時,函數返回多個值是非常方便的:

deffun(): ...return a, b但是很多C語言初學者在編寫某個函數,需要返回多個值時會感到困難,畢竟C語言的 return 語法只能返回一個值,返回多個值就會引起語法錯誤:

int fun(){ ...return a, b; // 非法}那麼,是不是C語言函數無法返回多個值呢?請繼續往下看。

「返回」多個值

雖然C語言的語法限定 return 語句只能返回一個值,但C語言函數完全可以向函數調用者傳遞多個值。可能有些讀者像小編一樣,嘗試過使用全局變量作為多值傳遞的手段:

int a, b;void fun(){ ... a = res1; b = res2;}int main(){ fun();printf("%d %d\n", a, b);return0;}上述C語言代碼中,fun() 函數會將最終處理結果 res1 和 res2 存入 a 和 b,利用全局變量的全局可見性,間接的將兩個結果「返回」給 main() 函數。這樣做當然沒問題,但是如果涉及到多線程編程,沒有同步保護的使用全局變量就不安全了,很容易給程序帶來意想不到的問題,所以,在實際的C語言程序開發中,極少使用這種方法。

怎樣才能更好的讓C語言函數返回多個值呢?

C語言區別其他大多數高級程式語言的特性是指針語法,事實上,C語言的指針非常強大,利用指針,我們能夠很輕易的讓C語言函數安全的「返回」多個值。

C語言的指針允許程序直接操作內存,所以函數可以將任意多的值放入內存(只要內存夠用),再將這些值的地址和訪問方式告訴調用者,那麼調用者完全可以將這些值從內存中取出,這樣的過程其實就實現了C語言函數「返回」任意多的值。

下面是一個使用C語言中的指針語法返回多個值的例子:

void fun(int *a, int *b){ ... *a = res1; *b = res2;}int main(){int x=1, y=2; fun(&x, &y);printf("%d %d\n", x, y);return0;}在上述C語言代碼中,fun() 函數接收兩個參數,不過這兩個參數都是 int 指針類型,main() 函數調用 fun() 時,將自己的局部變量 x 和 y 的地址傳遞給 fun(),此時 fun() 的參數 a 指向變量 x,參數 b 指向變量 y。

藉助於指針語法,fun() 函數可以直接操作 main() 函數中的變量 x 和 y,所以 fun() 函數不僅可以讀取 x 和 y 的初值,也可以在自己的內部邏輯處理完畢後,將處理結果直接寫到 x 和 y。這樣看來,甚至都無需 return 語法,C語言函數就能很方便的返回多個值。

小結

本節主要討論了C語言函數返回多個值的兩個方法:一是藉助全局變量,再就是使用指針。考慮到全局變量在多線程編程中需要做同步保護,比較麻煩,所以在實際的C語言程序開發中,需要返回多個值時,更多是藉助指針實現。

不過,如果需要返回的值比較多,通過被調用函數參數傳遞「返回值」就不方便了。事實上,如果某個函數的參數過多,也比較影響C語言程序的效率。針對這種情況,藉助指針聯合結構體語法,能夠實現更方便更安全的「返回值」傳遞。如果讀者對這種方法感到迷惑,可以閱讀本專欄的下一篇文章,感謝支持。

相關焦點

  • C語言陷阱與技巧第15節,為什麼每調用一次函數,就需要一次if判斷...
    在C語言程序開發中,調用一個有返回值的函數時,一般要對函數的返回值做判斷,以確定函數是否按照預期執行。如果被調用函數沒有按照預期執行,最好加上相應的錯誤處理代碼,否則最終編譯得到的C語言程序穩定性就不夠好,遇到一點點意外,可能就不會正常工作了。沒有判斷C語言函數的返回值,會有什麼問題?
  • C語言陷阱與技巧第8節,輸出適當的信息,有利於定位錯誤和異常代碼
    將任務拆分成子模塊後,每個子模塊常常被封裝成一個C語言函數,所以,最後的「堆積木」其實就是調用各個C語言函數。不過,每一個子模塊都有可能得到正常結果,也有可能得到異常結果,這通常用C語言函數的返回值區分。在「堆積木」階段調用各個函數時,應該根據被調用函數的返回值做不同的處理。
  • 帶參數的無返回值(void)函數如何返回處理結果?(附代碼)
    昨天有讀者問到一個問題,不論是否理解有誤姑且先將本文發出來。在軟體開發過程中有一種很常見的編程方法,就是即使將參數傳給無返回值的void函數也能實現對原始參數值的修改,這句話到底說的什麼意思,且看示例。
  • 對話框窗口過程返回值的解釋
    因為在傳統的C語言中,一個函數只能返回一個值,但是在對話框窗口過程中需要返回上述提到的兩種信息,那咋辦?需要想出一種方法來返回這兩種信息。方法如下對話框窗口過程的返回值表明了消息是否得到了處理。舉個例子,許多WM_NOTIFY消息處理函數可以用來被重寫為返回TRUE。如果希望一個列表視圖(ListView)的標籤取消編輯,則可以在LVN_BEGINLABELEDIT消息處理函數中返回TRUE。
  • 你知道C語言中函數調用和嵌套嗎?函數必學模塊,你不得不知!
    一、函數調用 什麼是函數調用呢?通常在C語言中,一個完整的項目程序是不可能在一個函數中實現所有的功能。而是由若干功能不同的函數來實現,並且函數之間會存在互相調用的情況。
  • LARGE函數:返回數組中第幾大值,對於數字排位一直很在行
    今天函數哥將像大家分享LARGE函數,LARGE函數用來返回某值在數列或數組中所處位置的排位,即第幾的位置排名。LARGE函數返回第幾排位的值功能:傳回資料組中第 k 大的數值您可以用這個函數來指定選取排在第幾位的值。語法:=LARGE(數組,第幾大值)1)數組:是您要從其中選取第 k 大的數值之陣列或資料範圍。
  • 零基礎java入門教程函數function實例化格式案例void返回值說明
    >執行語句;return 返回值;}返回值:函數運行後的結果的返回數據類型;參數類型:是形參的數據類型;形參:是一個變量,用於存儲調用函數時傳遞給函數的實參;實參:傳遞給形參的具體數值;return:用於結束函數;返回值:該值會返回給調用者;
  • C語言陷阱與技巧第13節,1位元組(Byte)一定等於8位(bit)嗎?C語言操作...
    在這些項目中,以嵌入式項目為代表,一般都需要嚴格控制內存的使用——使用 1 個字節(Byte)就能存放的值,絕對不定義 2 個字節寬度的變量。甚至,一些「摳門」的C語言程式設計師會將 1 個字節掰成若干個位(bit)使用。
  • 全國計算機等級考試二級C語言:函數的定義和返回值(4)
    C語言等級考試一直是廣大朋友比較頭痛的,針對此種情況21互聯特聘請了資深的老師,錄製了C語言等級考試課程,使廣大朋友能夠迅速掌握相應的知識點,順利通過考試。此視頻教程由21互聯提供,網易學院和21互聯聯合發布。
  • C語言編程:驗證哥德巴赫猜想
    a = b + c(其中a是大於等於6的整數,b和c是素數)這個問題就等價於:對於一個給定的大於等於4的偶數a,怎麼找到素數b和c呢?可以用循環的方法,把b的值從3循環到a-3,那麼對應的c的值就是a-3到3。然後我們分別對每一組的b和c值進行是否是素數的判斷。
  • 你有沒有想過,C語言 main 函數到底為啥這麼寫?
    但凡是學過C語言的人,都知道要先寫main函數,然而很多時候我們看到的main函數卻各有差異,這究竟是為啥?哪種是對的呢?今天我們就來聊聊main函數。那麼main函數一共有多少個版本呢?1、main()直接的mian()並沒有返回值,沒有入參。這種寫法實際來說,部分編譯器會顯示警告,並且會返回默認值為int。不過在C89標準中其實是可以的,由於沒有聲明返回類型,所以才會返回默認值int。
  • Excel Find函數與FindB函數使用方法,含用數組一次查找多個值
    在 Excel 中,查找指定字符在源字符串中的位置,既可以用 Find函數,也可以用 FindB函數,它們都有三個參數,所不同的是,前者把漢字、字母和數字都算一個字符,後者把漢字算兩個字節,數字和字母算一個字節。
  • 邏輯函數中利用IF函數判斷是與不是,利用NOT函數對參數值求反
    今日和大家繼續分享邏輯函數中的IF和NOT,這兩個函數的應用非常廣泛,很多接觸EXCEL函數的朋友最初都是從IF函數開始的,這個函數在EXCEL中的地位是永遠撼不動的。下面給大家詳細的講解。這是邏輯函數的第三講一.IF 判斷是與不是。
  • r語言work_r語言work函數 - CSDN
    (5) 一種相當完善、簡潔和高效的程序設計語言。它包括條件語句、循環語句、用戶自定義的遞歸函數以及輸入輸出接口。(6) R語言是徹底面向對象的統計程式語言。(7) R語言和其它程式語言、資料庫之間有很好的接口。(8) R語言是自由軟體,可以放心大膽地使用,但其功能卻不比任何其它同類軟體差。
  • 深入理解C語言
    但是,你知道這段程序的退出碼嗎?在ANSI-C下,退出碼是一些未定義的垃圾數。但在C89下,退出碼是3,因為其取了printf的返回值。為什麼printf函數返回3呢?因為其輸出了』4′, 』2′,』\n』 三個字符。而在C99下,其會返回0,也就是成功地運行了這段程序。你可以使用gcc的 -std=c89或是-std=c99來編譯上面的程序看結果。
  • 第五十三講 R-缺失值的注意事項及處理
    即mean = (1+2+4)/3mean (x,na.rm=T)通過運行x ==NA,我們找不到缺失值。像大多數其他R函數功能一樣方, 當任何一個參數為NA,==操作符返回NA。is.na()函數可以用來發現缺失值:該函數會返回一個邏輯向量TRUE(是缺失值)和FALSE(不是缺失值)。which()可以幫助找到缺失值具體是哪一個座位上。
  • 一日一技:從Python列表中刪除重複值
    從Python列表中刪除重複項列表是一個包含不同Python對象的容器,該對象可以是整數,字符串,布爾值等。它等同於其他程式語言中的數組。因此,在這裡我們將通過不同的方式來從列表中刪除重複值。在這節中,我們將學習:使用Set()方法 從列表中刪除重複項使用臨時列表從列表中刪除重複項。
  • C語言陷阱與技巧31節,都說void*指針是「萬能指針」,它萬能在哪
    在C語言程序開發中,一些比較成熟的庫函數常常會被使用。畢竟,如果手邊就有不錯的「輪子」可以用,沒有程式設計師願意再花費精力憑空造一個輪子出來。無非就是一個地址,它的類型只是用於說明數據結構的。因為 void 類型是一個特殊的類型,常被稱作「空類型」,C語言中沒有 void 類型的變量,所以在遇到 void 指針時,編譯器根本不知道如何解釋接下來的內存,甚至編譯器都不知道接下來多少內存屬於它。
  • 自考「C語言程序設計」模擬試題十一
    「c」    B.『\\』『    C.』W『   D. 』『  14.若有代數式3ae/bc,則不正確的c語言表達式是(     )  A.a/b/c*e*3    B.3*a*e/b/c    C.3*a*e/b*c    D.a*e/c/c*3  15.在C語言中,要求運算數必須是整型的運算符是(   )  A./    B.++   C
  • R語言:用R計算各種統計值
    percentile)四分位間距(quartile range)方差(variance)標準差(standard deviation)變異係數(coefficient of variance)正態分布(normal distribution)標準正態分布(standard normal distribution)使用R語言的內建實例數據框