知識(shí)分享:C/C++函數(shù)返回二維數(shù)組指針
C/C++從函數(shù)返回指針是常規(guī)操作,本文針對(duì)返回二維數(shù)組指針做了一些研究,并給出二維數(shù)組指針返回double?**類型指針的結(jié)論。

常規(guī)C/C++函數(shù)返回二維數(shù)組指針
(1)返回值返回二維數(shù)組指針
首先看通過返回值返回二維指針的簡(jiǎn)單情況:

上述代碼中,數(shù)據(jù)內(nèi)存從堆(heap)分配,因此函數(shù)結(jié)束后分配的存儲(chǔ)空間依然可用。調(diào)用方式:

(2)傳參返回二維數(shù)組指針
一些情況下,我們希望傳入一個(gè)指針,其在函數(shù)內(nèi)完成內(nèi)存分配。這個(gè)要求稍微復(fù)雜點(diǎn),其代碼為:

因?yàn)橐淖兌S指針的指向,傳參方式需要引用方式傳遞二維數(shù)組指針,于是參數(shù)為double***類型。代碼調(diào)用方式:

相對(duì)于返回值方式,參數(shù)方式理解上稍微難點(diǎn),也還容易理解。
返回二維靜態(tài)數(shù)組的double**指針
接著來到本文的重點(diǎn):返回二維靜態(tài)數(shù)組的double**指針。
一眼看過去,這個(gè)需求很好實(shí)現(xiàn):

遺憾的是,上面的代碼無法編譯通過,會(huì)出現(xiàn)如下錯(cuò)誤:
error: cannot initialize return object of type 'double **' with an lvalue of type 'double [10][10]'
錯(cuò)誤意思大概為A指向double?[10][10],但返回值要求double**,無法轉(zhuǎn)換。
編譯器不知道怎么轉(zhuǎn)換,試試強(qiáng)制轉(zhuǎn)換?

OK,編譯沒問題了,但問題轉(zhuǎn)到了調(diào)用上:

問題出在了A的轉(zhuǎn)換上:A[N][N]中的A其實(shí)是一維數(shù)組,每個(gè)值保存一個(gè)指針。
用下面代碼驗(yàn)證我們的想法:

調(diào)用上面的代碼重新運(yùn)行程序,完美,一切按照預(yù)期運(yùn)行!
通過引入Pointer1D我們成功讓程序運(yùn)行了,但我們知道Pointer1D是double*的別名,因此實(shí)際上可以直接用double*的方式寫代碼:

運(yùn)行程序,也完全沒毛病。至此我們順利實(shí)現(xiàn)了從二維靜態(tài)數(shù)組返回double**指針的目的。
但有個(gè)問題仍然沒繞開:一定要引入新變量并初始化,不能直接(或通過類型轉(zhuǎn)換)返回A嗎?
答案是不能,因?yàn)橹苯?或通過類型轉(zhuǎn)換)返回A存在信息丟失。
以3維方陣為例,double?A[3][3]其實(shí)保存了12個(gè)數(shù)據(jù)信息:9個(gè)保存矩陣的值,這個(gè)很好理解;此外還需要額外3個(gè)double*數(shù)據(jù),分別指向A的每一行起始位置。有了這12個(gè)數(shù)據(jù),A[i][j]實(shí)際中會(huì)轉(zhuǎn)換成如下方式取值:

即:根據(jù)i得到行的指針,再根據(jù)j偏移得到A[i][j]的指針,最后取值得到A[i][j]。
A[N][N]中的A本質(zhì)上是一維數(shù)組,只保存了三個(gè)double*指針的值。將其強(qiáng)制轉(zhuǎn)換成double**:double**?a?=?(double**)A,a的值與A確實(shí)一樣,但a[i]?=?A[i]!
可以通過下面代碼驗(yàn)證:

其輸出結(jié)果為:

a確實(shí)和A相等,但是A[0]不等于a[0]!因?yàn)閍[0]未賦值,取值a[0][0]程序直接就會(huì)掛掉!。
這就是為什么上面可正常運(yùn)行的代碼要引入一個(gè)額外數(shù)組,并初始化才能正常運(yùn)行的原因。
其實(shí),常規(guī)返回二維數(shù)組指針的代碼已經(jīng)透露了原因:生成二維數(shù)組,不僅需要double**的數(shù)據(jù),還需要生成包含n個(gè)double*的數(shù)組并初始化:

而直接從A[N][N]直接轉(zhuǎn)化,只對(duì)ptr賦值了,ptr[i]并沒有初始化,出現(xiàn)Segment Fault也就在預(yù)料之中了。
總結(jié)
本文介紹了三種C/C++函數(shù)返回二維數(shù)組指針的方式,并深入剖析了二維靜態(tài)數(shù)組轉(zhuǎn)換成double**存在的問題及解決方案。實(shí)際上,靜態(tài)二維數(shù)組返回double**等同于該問題:如何將二維數(shù)組轉(zhuǎn)換成double**指針?
通過上面的分析,我們知道直接轉(zhuǎn)換的做法是行不通的,需要引入一個(gè)額外數(shù)組并初始化才能正確轉(zhuǎn)換。
微信公眾號(hào):C語言編程學(xué)習(xí)基地
分享(源碼、項(xiàng)目實(shí)戰(zhàn)視頻、項(xiàng)目筆記,基礎(chǔ)入門教程)
歡迎轉(zhuǎn)行和學(xué)習(xí)編程的伙伴,利用更多的資料學(xué)習(xí)成長(zhǎng)比自己琢磨更快哦!
