程序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的值。
---------------------------------------------------------------
你要弄清楚的是指針變量和指針所指的變量(可能是一片內存)。
指針變量和普通變量一樣存儲的,