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

在看林銳的書。
7.4指針參數是如何傳遞內存的?
----------------------下邊的例子是我確定犯過的錯誤,並且之後不能保證就記得住不犯
特意記下來。
 

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

若是函數的參數是一個指針,不要期望用該指針去申請動態內存。示例 7-4-1 中, Test 數的語句 GetMemory(str, 200) 並無使 str 得到指望的內存, str 依舊是 NULL ,爲何?
v oid 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"); // 運行錯誤
}
示例 7-4-1  試圖用指針參數申請動態內存
毛病出在函數 GetMemory 中。編譯器老是要爲函數的每一個參數製做臨時副本,指針參數 p 的副本是  _p ,編譯器使  _p = p 。若是函數體內的程序修改了 _p 的內容,就致使參數 p 的內容做相應的修改。這就是指針能夠用做輸出參數的緣由。在本例中, _p 申請了新的內存,只是把 _p 所指的內存地址改變了,可是 p 絲毫未變。因此函數 GetMemory 並不能輸出任何東西。事實上,每執行一次 GetMemory 就會泄露一塊內存,由於沒有用 free 釋放內存。
若是非得要用指針參數去申請內存,那麼應該改用「指向指針的指針」,見示例 7-4- 2
void GetMemory2(char **p, int num)
{
* 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用指向指針的指針申請動態內存
因爲 「指向指針的指針」這個概念不容易理解,咱們能夠用函數返回值來傳遞動態內存。這種方法更加簡單,見示例 7-4- 3
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);
}
示例 7-4- 用函數返回值來傳遞動態內存
用函數返回值來傳遞動態內存這種方法雖然好用,可是經常有人把 return 語句用錯了。這裏強調不要用 return 語句返回指向「棧內存」的指針,由於該內存在函數結束時自動消亡,見示例 7-4- 4
char * GetString (void)
{
char p[] = "hello world";
return p; //  編譯器將提出警告
}
void Test4(void)
{
char * str  =   NULL;
str  =  GetString (); //  str  的內容是垃圾
cout<<  str  << endl;
}
示例 7-4- return 語句返回指向「棧內存」的指針
用調試器逐步跟蹤 Test4 ,發現執行 str = GetString 語句後 str 再也不是 NULL 指針,可是 str 的內容不是 hello world 而是垃圾。
若是把 示例 7-4- 4 改寫成 示例 7-4- 5 ,會怎麼樣?
char *Get String 2(void)
{
char *p = "hello world";
return p;
}
void Test5(void)
{
char * str  = NULL;
str  =   Get String 2();
cout<<  str  << endl;
}
示例 7-4- return 語句返回常量字符串
函數 Test5 運行雖然不會出錯,可是函數 GetString2 的設計概念倒是錯誤的。由於 GetString2 內的「 hello world 」是常量字符串,位於靜態存儲區,它在程序生命期內恆定不變。不管何時調用 GetString2 ,它返回的始終是同一個「只讀」的內存塊。
相關文章
相關標籤/搜索