函數參數的傳遞問題(一級指針和二級指針)?[轉]
原以為自己對指針掌握了,卻還是對這個問題不太明白。請教!??
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序3:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
10??
程序4:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????*p=100;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
100??
為什么???
?
?
?
?
---------------------------------------------------------------??
?
1.被分配內存的是行參s,p沒有分配內存??
2.被分配內存的是行參s指向的指針p,所以分配了內存??
---------------------------------------------------------------??
?
不是指針沒明白,是函數調用的問題!看看這段:??
?
7.4指針參數是如何傳遞內存的???
???????????如果函數的參數是一個指針,不要指望用該指針去申請動態內存。示例7-4-1中,Test函數的語句GetMemory(str,??200)并沒有使str獲得期望的內存,str依舊是NULL,為什么???
?
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"
;????????????//??運行錯誤??
}??
示例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-3??用函數返回值來傳遞動態內存??
?
用函數返回值來傳遞動態內存這種方法雖然好用,但是常常有人把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-4??return語句返回指向“棧內存”的指針??
?
用調試器逐步跟蹤Test4,發現執行str??=??GetString語句后str不再是NULL指針,但是str的內容不是“hello??world”而是垃圾。??
如果把示例7-4-4改寫成示例7-4-5,會怎么樣???
?
char??*GetString2(void)??
{??
???????????char??*p??=??"hello??world";??
???????????return??p;??
}??
void??Test5(void)??
{??
???????????char??*str??=??NULL;??
???????????str??=??GetString2();??
???????????cout<<??str??<<??endl;??
}??
示例7-4-5??return語句返回常量字符串??
?
函數Test5運行雖然不會出錯,但是函數GetString2的設計概念卻是錯誤的。因為GetString2內的“hello??world”是常量字符串,位于靜態存儲區,它在程序生命期內恒定不變。無論什么時候調用GetString2,它返回的始終是同一個“只讀”的內存塊。??
?
---------------------------------------------------------------??
?
看看林銳的《高質量的C/C++編程》呀,上面講得很清楚的??
---------------------------------------------------------------??
?
對于1和2:??
如果傳入的是一級指針S的話,??
那么函數中將使用的是S的拷貝,??
要改變S的值,只能傳入指向S的指針,即二級指針??
?
---------------------------------------------------------------??
?
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??//??s是值參,??函數返回后就回復傳遞前的數值,無法帶回分配的結果??
}??
這個和調用??void??func??(int??i)??{i=1;};??一樣,退出函數體,i指復原的??
?
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??//??這個是可以的??
}??
等價于??
void??int??func(int??*??pI)??{*pI=1;}??pI指針不變,指針指向的數據內容是變化的??
值參本身不變,但是值參指向的內存的內容發生了變化。??
?
程序3:??
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??????????????????//??等同于第一個問題,??b的地址并沒有被返回??
}??
?
程序4:??
?
void??fun(int??*p)??
{??
???????*p=100;????//??okay??
}??
?
?
?
?
---------------------------------------------------------------??
?
其實樓主的問題和指針沒有多大關系,就是行參和值參的問題??
?
函數調用的時候,值參傳遞的是數值,是不會返回的??
這個數值,在函數體內部相當于一個變量,是可以改變,但是這個改變是無法帶出函數體外部的??
?
---------------------------------------------------------------??
?
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);//傳過來的是P所指的地址,并不是P的地址,所以改變S不會改變P??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);//S指向的是P的地址,所以改變了P所指的內存單元.??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序3:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);道理同第一個程序.??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
10??
程序4:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????*p=100;//參數P和實參P所指的內存單元是相同的.所以改變了參數P的內存單元內容,就改變了實參??
?????????????????????//的內存單元內容??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
100??
為什么???
---------------------------------------------------------------??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
?
?
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??
}??
?
myMalloc(p)的執行過程:??
分配一個臨時變量char??*s,s的值等于p,也就是NULL,但是s占用的是與p不同的內存空間。此后函數的執行與p一點關系都沒有了!只是用p的值來初始化s。??
然后s=(char??*)??malloc(100),把s的值賦成malloc的地址,對p的值沒有任何影響。p的值還是NULL。??
注意指針變量只是一個特殊的變量,實際上它存的是整數值,但是它是內存中的某個地址。通過它可以訪問這個地址。??
?
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序2是正確的,為什么呢?看一個執行過程就知道了:??
myMalloc(&p);將p的地址傳入函數,假設存儲p變量的地址是0x5555,則0x5555這個地址存的是指針變量p的值,也就是Ox5555指向p。??
調用的時候同樣分配一個臨時變量char??**s,此時s??的值是&p的值也就是0x5555,但是s所占的空間是另外的空間,只不過它所指向的值是一個地址:Ox5555。??
*s=(char??*)??malloc(100);這一句話的意思是將s所指向的值,也就是0x5555這個位置上的變量的值賦為(char??*)??malloc(100),而0x5555這個位置上存的是恰好是指針變量p,這樣p的值就變成了(char??*)??malloc(100)的值。即p的值是新分配的這塊內存的起始地址。??
?
這個問題理解起來有點繞,關鍵是理解變量作函數形參調用的時候都是要分配一個副本,不管是傳值還是傳址。傳入后就和形參沒有關系了,它不會改變形參的值。myMalloc(p)不會改變p的值,p的值當然是NULL,它只能改變p所指向的內存地址的值。但是myMalloc(&p)為什么就可以了,它不會改變(&p)的值也不可能改變,但是它可以改變(&p)所指向內存地址的值,即p的值。??
?
---------------------------------------------------------------??
?
你要弄清楚的是指針變量和指針所指的變量(可能是一片內存)。??
?
指針變量和普通變量一樣存儲的,??
?
如int??*p;??int??i;??p和i都是變量,都占用一個字的內存,都可
原以為自己對指針掌握了,卻還是對這個問題不太明白。請教!??
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序3:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
10??
程序4:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????*p=100;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
100??
為什么???
?
?
?
?
---------------------------------------------------------------??
?
1.被分配內存的是行參s,p沒有分配內存??
2.被分配內存的是行參s指向的指針p,所以分配了內存??
---------------------------------------------------------------??
?
不是指針沒明白,是函數調用的問題!看看這段:??
?
7.4指針參數是如何傳遞內存的???
???????????如果函數的參數是一個指針,不要指望用該指針去申請動態內存。示例7-4-1中,Test函數的語句GetMemory(str,??200)并沒有使str獲得期望的內存,str依舊是NULL,為什么???
?
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"

}??
示例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-3??用函數返回值來傳遞動態內存??
?
用函數返回值來傳遞動態內存這種方法雖然好用,但是常常有人把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-4??return語句返回指向“棧內存”的指針??
?
用調試器逐步跟蹤Test4,發現執行str??=??GetString語句后str不再是NULL指針,但是str的內容不是“hello??world”而是垃圾。??
如果把示例7-4-4改寫成示例7-4-5,會怎么樣???
?
char??*GetString2(void)??
{??
???????????char??*p??=??"hello??world";??
???????????return??p;??
}??
void??Test5(void)??
{??
???????????char??*str??=??NULL;??
???????????str??=??GetString2();??
???????????cout<<??str??<<??endl;??
}??
示例7-4-5??return語句返回常量字符串??
?
函數Test5運行雖然不會出錯,但是函數GetString2的設計概念卻是錯誤的。因為GetString2內的“hello??world”是常量字符串,位于靜態存儲區,它在程序生命期內恒定不變。無論什么時候調用GetString2,它返回的始終是同一個“只讀”的內存塊。??
?
---------------------------------------------------------------??
?
看看林銳的《高質量的C/C++編程》呀,上面講得很清楚的??
---------------------------------------------------------------??
?
對于1和2:??
如果傳入的是一級指針S的話,??
那么函數中將使用的是S的拷貝,??
要改變S的值,只能傳入指向S的指針,即二級指針??
?
---------------------------------------------------------------??
?
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??//??s是值參,??函數返回后就回復傳遞前的數值,無法帶回分配的結果??
}??
這個和調用??void??func??(int??i)??{i=1;};??一樣,退出函數體,i指復原的??
?
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??//??這個是可以的??
}??
等價于??
void??int??func(int??*??pI)??{*pI=1;}??pI指針不變,指針指向的數據內容是變化的??
值參本身不變,但是值參指向的內存的內容發生了變化。??
?
程序3:??
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??????????????????//??等同于第一個問題,??b的地址并沒有被返回??
}??
?
程序4:??
?
void??fun(int??*p)??
{??
???????*p=100;????//??okay??
}??
?
?
?
?
---------------------------------------------------------------??
?
其實樓主的問題和指針沒有多大關系,就是行參和值參的問題??
?
函數調用的時候,值參傳遞的是數值,是不會返回的??
這個數值,在函數體內部相當于一個變量,是可以改變,但是這個改變是無法帶出函數體外部的??
?
---------------------------------------------------------------??
?
程序1:??
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);//傳過來的是P所指的地址,并不是P的地址,所以改變S不會改變P??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);//S指向的是P的地址,所以改變了P所指的內存單元.??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序3:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????int??b=100;??
???????p=&b;??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);道理同第一個程序.??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
10??
程序4:??
#include<stdio.h>??
?
void??fun(int??*p)??
{??
???????*p=100;//參數P和實參P所指的內存單元是相同的.所以改變了參數P的內存單元內容,就改變了實參??
?????????????????????//的內存單元內容??
}??
?
main()??
{??
???????int??a=10;??
???????int??*q;??
???????q=&a;??
???????printf("%d/n",*q);??
???????fun(q);??
???????printf("%d/n",*q);??
???????return??0;??
}??
結果為??
10??
100??
為什么???
---------------------------------------------------------------??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(p);????//這里的p實際還是NULL,p的值沒有改變,為什么???
?????if(p)??free(p);??
}??
?
?
void??myMalloc(char??*s)??//我想在函數中分配內存,再返回??
{??
?????s=(char??*)??malloc(100);??
}??
?
myMalloc(p)的執行過程:??
分配一個臨時變量char??*s,s的值等于p,也就是NULL,但是s占用的是與p不同的內存空間。此后函數的執行與p一點關系都沒有了!只是用p的值來初始化s。??
然后s=(char??*)??malloc(100),把s的值賦成malloc的地址,對p的值沒有任何影響。p的值還是NULL。??
注意指針變量只是一個特殊的變量,實際上它存的是整數值,但是它是內存中的某個地址。通過它可以訪問這個地址。??
?
程序2:void??myMalloc(char??**s)??
{??
?????*s=(char??*)??malloc(100);??
}??
?
void??main()??
{??
?????char??*p=NULL;??
?????myMalloc(&p);????//這里的p可以得到正確的值了??
?????if(p)??free(p);??
}??
程序2是正確的,為什么呢?看一個執行過程就知道了:??
myMalloc(&p);將p的地址傳入函數,假設存儲p變量的地址是0x5555,則0x5555這個地址存的是指針變量p的值,也就是Ox5555指向p。??
調用的時候同樣分配一個臨時變量char??**s,此時s??的值是&p的值也就是0x5555,但是s所占的空間是另外的空間,只不過它所指向的值是一個地址:Ox5555。??
*s=(char??*)??malloc(100);這一句話的意思是將s所指向的值,也就是0x5555這個位置上的變量的值賦為(char??*)??malloc(100),而0x5555這個位置上存的是恰好是指針變量p,這樣p的值就變成了(char??*)??malloc(100)的值。即p的值是新分配的這塊內存的起始地址。??
?
這個問題理解起來有點繞,關鍵是理解變量作函數形參調用的時候都是要分配一個副本,不管是傳值還是傳址。傳入后就和形參沒有關系了,它不會改變形參的值。myMalloc(p)不會改變p的值,p的值當然是NULL,它只能改變p所指向的內存地址的值。但是myMalloc(&p)為什么就可以了,它不會改變(&p)的值也不可能改變,但是它可以改變(&p)所指向內存地址的值,即p的值。??
?
---------------------------------------------------------------??
?
你要弄清楚的是指針變量和指針所指的變量(可能是一片內存)。??
?
指針變量和普通變量一樣存儲的,??
?
如int??*p;??int??i;??p和i都是變量,都占用一個字的內存,都可