1. 程式人生 > >對實參與形參之間資料傳輸的一些理解(指標指向、儲存位置)

對實參與形參之間資料傳輸的一些理解(指標指向、儲存位置)

首先我們先通過一題來了解一下實參與形參間值傳遞的方式。

例題1:

void Getmemory(char *p)
{
    p=(char *)malloc(100);
}
int main()
{
    char *str=NULL;
    Getmemory(str);
    strcpy(str,"hello!");
    cout<<str<<endl;
}

此題無法正確輸出結果“hellow!”。

原因是:在main函式中,首先生成一個指標str指向NULL,然後將str指標傳入Getmemory函式。注意!此時在Getmemory函式中的指標p是str的一個副本。

即str指向了NULL,p也指向了NULL,但是在Getmemory中執行分配記憶體的是p指標,str並沒有被分配記憶體!所以接下來的strcpy函式無法正確執行。

那麼該如何解決這個問題,使str能夠正確分配到記憶體呢?

方法一:

採用return的方式,將Getmemory執行的結果返還給main函式。

char *Getmemory(char *p)
{
    return p=(char *)malloc(100);
}
int main()
{
    char *str=NULL;
    str=Getmemory(str);
    strcpy(str,"hello!");
    cout<<str<<endl;
}   

我們將分配好記憶體的p指標返還給main函式,賦值給str指標,所以str也分配好了記憶體。如果函式體返回的值不止一個怎麼辦呢?

通過方法一,我們可以提前生成一個結構體,其成員函式是所有要返回的值,return這個結構體就行。

方法二:

採用二級指標的方式,即指標的指標,將p指標的地址p1(1、p指標自身同樣佔有記憶體空間,p1指向p 2、地址也是個指標)作為引數傳入函式中,生成副本指標p2,p2指標同樣指向p指標所在的記憶體空間,即p2也指向p。在傳入的函式中對p2所指向的內容(即p指標)進行更改就可以改變p的賦值。

void Getmemory(char **p)
{
    *p=(char *)malloc(100);
}
int main()
{
    char *str=NULL;
    Getmemory(&str);
    strcpy(str,"hello!");
    cout<<str<<endl;
}

我們可以發現,將str指標的地址傳入Getmemory函式中,生成一個副本指標p,此時p指向的值為str指標。我們的目標是給str指標分配記憶體空間,所以要對*p(取內容)進行記憶體分配,而不是對p本身進行記憶體分配。指標關係如下圖所示。

拓展:

對指標的操作分為兩部分,一個是對指標自身進行操作,第二個是對指標指向的內容進行操作。

方法三:

在C++中,可以採用引用的方式來處理(C中不可以,沒有引用的概念)。將b宣告為a的引用,不需要為b另外開闢記憶體單元,b和a佔記憶體中的同一個儲存單元。(int a=1;int &b=a;      char *p=NULL; char *&p2=p;)

void Getmemory(char *&p)
{
     p=(char *)malloc(100);
}
int main()
{
    char *str=NULL;
    Getmemory(str);
    strcpy(str,"hello!");
    cout<<str<<endl;
}

將指標str的引用指標p傳入Getmemory中,對指標p的改動同樣就是對指標str的改動,p是str的別名。

例題2:

char *Getmemory()
{
    char p[]="hello!";
    return p;
}
int main()
{
    char *str=NULL;
    str=Getmemory();
    cout<<str<<endl;
}

此題能否正確列印hello呢?答案是否。這是為什麼呢?上文你不是說通過return返回就行了嗎?

這是因為,指標p確確實實返回給了str,但是指標p指向的內容“hello!”已經消亡了。在Getmemory函式中陣列p為區域性變數,其生存週期為函式的執行期間,當函式執行完畢,陣列p就消亡了,那麼指標p指向的內容就沒有了。

那麼該如何解決呢?

static。利用static修飾陣列p,使其成為靜態區域性變數,改變它的生存週期,使其生存週期擴充套件到該CPP執行結束,那麼此時str接收到的即為p陣列的首地址,陣列p也沒有消亡,實現列印。

static char p[]="hello!";

例題3:

如果把例題2的 char p[]="hello!";換成 char *p="hello!"; 呢?

答案是可以正常列印。這又是為什麼呢?

這是因為,在例題2中“hello!”儲存在名為p的陣列中,陣列p是區域性變數,隨著函式執行結束消亡。但是在本題中,“hello!”是個字串,儲存在常量區中,我們只是用一個指標p去指向它。return後,指標p消亡了,但字串仍在常量區中,指標str指向字串。所以可列印。