1. 程式人生 > 其它 >C語言函式傳參:指標的指標

C語言函式傳參:指標的指標

技術標籤:CC指標嵌入式

文章目錄

前言

今天同事問了一個問題:在函式引數中傳遞指標的指標,很常用的一個場景,重新梳理一下記錄於此,以後如果有類似的問題直接發這篇小總結就可以了。

程式碼:版本1

void do_malloc(char *p, int size)
{
    p = (char *)malloc(size + 1);
    memset(p, 0, size + 1);
}


int main(int argc, char *argv[])
{
    char *pData = 0;
    do_malloc(pData, 128);
    sprintf(pData, "%s", "abc");
    printf(pData);
    return 0;
}

程式碼本意是:do_work()函式向系統堆空間申請size個位元組的空間,然後返回給main函式中的pData指標
但是,執行的時候報錯:Segmentation fault (core dumped)

分析原因

我們可以把char*型別的指標看成一個遙控器,如果給這個指標賦值,就相當於把這個遙控器與一個裝置進行繫結,可以通過遙控器來控制這個裝置。

執行char *pData = 0;

pData內容為空,相當於這個遙控器沒有與任何裝置繫結,如下圖:

執行do_work(pData, 128);

這裡傳遞的引數是pData本身,所以進入void do_work(char *p, int size)

函式之後,實參pData的內容就賦值給形參p,所以指標p的內容也為空,也就是說:p這個遙控器也沒有與任何裝置繫結,如下圖:

執行p = (char *)malloc(size + 1);

這句話的作用是把申請到的堆空間的首地址,賦值給p。就是說:現在p指向了記憶體中的一塊空間,就相當於一個p這個遙控器與一個裝置進行綁定了,可以控制這個裝置了,如下圖:

到這裡就已經看到程式崩潰的原因了:雖然給指標p賦值了,但是實參pData中的內容一直為空,因此從do_malloc函式返回之後,pData仍然是一個空指標,所以就崩潰了。當然,p指向的堆空間也就洩露了。

程式碼:版本2

程式碼的本意是在do_malloc函式中申請堆空間,然後把這塊空間的首地址賦值給pData。在do_malloc函式中,呼叫系統函式malloc成功之後返回所分配空間的首地址,關鍵是要把這個首地址送給pData指標,也就是說要讓pData指標變數中的值等於這個堆空間的首地址。

那應該如何通過中間的一個函式來完成這個功能呢,如下程式碼:

void do_malloc(char **p, int size)
{
    *p = (char *)malloc(size + 1);
    memset(*p, 0, size + 1);
}


int main(int argc, char *argv[])
{
    char *pData = 0;
    do_malloc(&pData, 128);
    sprintf(pData, "%s", "abc");
    printf(pData);
    return 0;
}

執行char *pData = 0;

這一句沒有變化。

執行do_malloc(&pData, 128);

pData指標的地址作為實參進行傳遞,因為pData本身就是一個指標,加上取地址符&,就是指標的指標(二級指標),因此do_malloc函式的第一個引數就要定義成char**型別,此時示意如圖:

p此時是一個二級指標,引數賦值之後,p裡面的內容就變成了pData這個指標變數的地址,也就是說p指向了pData這個變數。

執行*p = (char *)malloc(size + 1);

這句話首先搞明白*p是啥意思,剛才說了,p是一個指標,它指向了pData這個變數。那麼在p前面加上取值操作符*,就相當於是取出指標p中的值,它裡面的值就是pData!
因此,malloc函式返回的堆空間首地址,就相當於是賦值給了pData,如下圖:

此時,pData這個遙控器就與分配的這塊堆空間繫結在一起,隨後再操作pData就沒有問題了。


【原創宣告】

> 作者:道哥(公眾號: IOT物聯網小鎮)
> 知乎:道哥
> B站:道哥分享
> 掘金:道哥分享
> CSDN:道哥分享

如果覺得文章不錯,請轉發、分享給您的朋友。


我會把十多年嵌入式開發中的專案實戰經驗進行總結、分享,相信不會讓你失望的!

長按下圖二維碼關注,每篇文章都有乾貨。


轉載:歡迎轉載,但未經作者同意,必須保留此段宣告,必須在文章中給出原文連線。




推薦閱讀

[1] 原來gdb的底層除錯原理這麼簡單
[2] 生產者和消費者模式中的雙緩衝技術
[3] 深入LUA指令碼語言,讓你徹底明白除錯原理
[4] 一步步分析-如何用C實現面向物件程式設計
[5] 關於加密、證書的那些事