指針參數是如何傳遞內存的?

若是函數的參數是一個指針,不要期望用該指針去申請動態內存。函數

Test 函數的語句GetMemory(str, 200)並無使str得到指望的內存,str 依舊是NULL

爲何?spa

void GetMemory(char *p, int num)設計

{指針

p = (char *)malloc(sizeof(char) *num);調試

}內存

void Test(void)字符串

{編譯器

char *str = NULL;編譯

GetMemory(str, 100); // str仍然爲 NULL程序

strcpy(str, "hello");//運行錯誤

}

 試圖用指針參數申請動態內存


毛病出在函數 GetMemory中。編譯器老是要爲函數的每一個參數製做臨時副本,指針

參數p的副本是 _p,編譯器使 _p = p 。若是函數體內的程序修改了_p的內容,就致使

參數p的內容做相應的修改。這就是指針能夠用做輸出參數的緣由。在本例中,_p 申請

了新的內存,只是把_p所指的內存地址改變了,可是p 絲毫未變。因此函數GetMemory

並不能輸出任何東西。事實上,每執行一次GetMemory就會泄露一塊內存,由於沒有用

free釋放內存。

若是非得要用指針參數去申請內存,那麼應該改用「指向指針的指針」,見示例:

void GetMemory2(char **p, intnum)

{

*p = (char *)malloc(sizeof(char)* num);

}

void Test2(void)

{

char *str = NULL;

GetMemory2(&str, 100); //注意參數是 &str,而不是str

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

示例7-4-2用指向指針的指針申請動態內存

因爲「指向指針的指針」這個概念不容易理解,咱們能夠用函數返回值來傳遞動態

內存。這種方法更加簡單。

char *GetMemory3(int num)

{

char *p = (char*)malloc(sizeof(char) * num);

return p;

}

void Test3(void)

{

char *str = NULL;

str = GetMemory3(100);

strcpy(str, "hello");

cout<< str << endl;

free(str);

}

用函數返回值來傳遞動態內存

用函數返回值來傳遞動態內存這種方法雖然好用,可是經常有人把return語句用錯

了。這裏強調不要用return語句返回指向「棧內存」的指針,由於該內存在函數結束時

自動消亡,見示例

char *GetString(void)

{

char p[] = "helloworld";

return p; //編譯器將提出警告

}

void Test4(void)

{

char *str = NULL;

str = GetString(); // str的內容是垃圾

cout<< str << endl;

}

 return語句返回指向「棧內存」的指針

用調試器逐步跟蹤Test4,發現執行str = GetString語句後str 再也不是NULL 指針,

可是str的內容不是helloworld而是垃圾。

若是將上示例改寫成以下會怎麼樣?

char *GetString2(void)

{

char *p = "helloworld";

return p;

}

void Test5(void)

{

char *str = NULL;

str = GetString2();

cout<< str << endl;

}

return語句返回常量字符串


函數Test5運行雖然不會出錯,可是函數GetString2 的設計概念倒是錯誤的。由於

GetString2內的「hello world」是常量字符串,位於靜態存儲區,它在程序生命期內

恆定不變。不管何時調用GetString2,它返回的始終是同一個「只讀」的內存塊。

相關文章
相關標籤/搜索