如今幾乎找不到只專注於一門程式語言的程式設計師了。大多數程式設計師在自己平時的工作和生活中,一般都使用不止一門程式語言,例如小編在工作中主要使用的是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語言程序的效率。針對這種情況,藉助指針聯合結構體語法,能夠實現更方便更安全的「返回值」傳遞。如果讀者對這種方法感到迷惑,可以閱讀本專欄的下一篇文章,感謝支持。