以一段代碼切入主題吧。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function1(int *v)
{
v = (int *)malloc(sizeof(int));
*v = 100;
}
void main()
{
int *v = NULL;
function1(v);
printf("%d\n",*v);
}
你會發現這段代碼不能運行,為什麼呢?不是傳遞的指針嗎?又不是值傳遞。一直以來,在C程序員的腦子裡都知道值傳遞和指針傳遞這個概念(不要跟我說不知道,否則你就說我不是C程序員),但卻沒有真正理解函數參數傳遞的本質。
跟著我後面走,忘卻什麼值和指針,亂七八糟的東西,煩死了。你現在應該想明白,指針就是一個變量,存放的是地址,不過也是一個值罷了,只不過特殊一點。再明確一點,函數參數的傳遞實際上是一個拷貝的過程,而且離奇的是,都是拷貝。
現在回答我,主函數function1(v)是不是傳遞了一個值(這個值是一個地址)給被調函數?那麼被調函數就把這個值(也就是地址)拷貝了下來。本來沒有什麼事的,狗血的是他執行了v = (int *)malloc(sizeof(int));這樣一條語句,這條語句什麼意思啊,哦,申請一塊內存,並把這塊內存的地址返回給v,呵呵,悄然把地址修改啦。這時主函數和被調函數中的指針指向的東西沒有半毛關系了,主函數中v還是NULL,所以……
怎麼修改呢?看下面的代碼
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void function2(int **v)
{
*v = (int *)malloc(sizeof(int));
**v = 10;
}
void main()
{
int *v;
function2(&v);
printf("%d\n",*v);
}
被調函數要求傳遞指針的地址,好,那就把主函數中某個指針的地址復制過來。注意哦*v = (int *)malloc(sizeof(int));這條語句分配一塊內存,返回給誰呢?指針的指針的地址還是指針,當然是指針了,想明白。(在被調函數中**v代表指針指向的值,*v代表指針,v代表指針的地址),也許你還不明白,看個圖。
我們驚奇地發現,我們只是把指針的地址復制了過來,但這個地址仍然指向這個指針,明白了吧。
其實我不在忙喜歡這種方式,我喜歡要麼在被調函數外面先分配好內存,再把指針傳遞進去,要麼干脆在被調函數裡面定義指針,分配內存,然後返回指針就好了,這樣不容易出錯。