中文字幕理论片,69视频免费在线观看,亚洲成人app,国产1级毛片,刘涛最大尺度戏视频,欧美亚洲美女视频,2021韩国美女仙女屋vip视频

打開(kāi)APP
userphoto
未登錄

開(kāi)通VIP,暢享免費(fèi)電子書(shū)等14項(xiàng)超值服

開(kāi)通VIP
C語(yǔ)言中二級(jí)指針做參數(shù) (轉(zhuǎn))

C語(yǔ)言中二級(jí)指針做參數(shù) (轉(zhuǎn))  

2012-02-09 10:19:55|  分類(lèi): 術(shù)業(yè)專(zhuān)攻 |  標(biāo)簽:c語(yǔ)言  指針參數(shù)   |字號(hào) 訂閱


程序1:
void myMalloc(char *s) //我想在函數(shù)中分配內(nèi)存,再返回
{
s=(char *) malloc(100);
}
void main()
{
char *p=NULL;
myMalloc(p); //這里的p實(shí)際還是NULL,p的值沒(méi)有改變,為什么?
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;
}
結(jié)果為
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;
}
結(jié)果為
10
100
為什么?
---------------------------------------------------------------
1.被分配內(nèi)存的是行參s,p沒(méi)有分配內(nèi)存
2.被分配內(nèi)存的是行參s指向的指針p,所以分配了內(nèi)存
---------------------------------------------------------------
不是指針沒(méi)明白,是函數(shù)調(diào)用的問(wèn)題!看看這段:
7.4指針參數(shù)是如何傳遞內(nèi)存的?
如果函數(shù)的參數(shù)是一個(gè)指針,不要指望用該指針去申請(qǐng)動(dòng)態(tài)內(nèi)存。示例7-4-1中,Test函數(shù)的語(yǔ)句GetMemory(str, 200)并沒(méi)有使str獲得期望的內(nèi)存,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"); // 運(yùn)行錯(cuò)誤
}
示例7-4-1 試圖用指針參數(shù)申請(qǐng)動(dòng)態(tài)內(nèi)存
毛 病出在函數(shù)GetMemory中。編譯器總是要為函數(shù)的每個(gè)參數(shù)制作臨時(shí)副本,指針參數(shù)p的副本是 _p,編譯器使 _p = p。如果函數(shù)體內(nèi)的程序修改了_p的內(nèi)容,就導(dǎo)致參數(shù)p的內(nèi)容作相應(yīng)的修改。這就是指針可以用作輸出參數(shù)的原因。在本例中,_p申請(qǐng)了新的內(nèi)存,只是把 _p所指的內(nèi)存地址改變了,但是p絲毫未變。所以函數(shù)GetMemory并不能輸出任何東西。事實(shí)上,每執(zhí)行一次GetMemory就會(huì)泄露一塊內(nèi)存,因 為沒(méi)有用free釋放內(nèi)存。
如果非得要用指針參數(shù)去申請(qǐng)內(nèi)存,那么應(yīng)該改用“指向指針的指針”,見(jiàn)示例7-4-2。
void GetMemory2(char **p, int num)
{
*p = (char *)malloc(sizeof(char) * num);
}
void Test2(void)
{
char *str = NULL;
GetMemory2(&str, 100); // 注意參數(shù)是 &str,而不是str
strcpy(str, "hello");
cout<< str << endl;
free(str);
}
示例7-4-2用指向指針的指針申請(qǐng)動(dòng)態(tài)內(nèi)存
由于“指向指針的指針”這個(gè)概念不容易理解,我們可以用函數(shù)返回值來(lái)傳遞動(dòng)態(tài)內(nèi)存。這種方法更加簡(jiǎn)單,見(jiàn)示例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 用函數(shù)返回值來(lái)傳遞動(dòng)態(tài)內(nèi)存
用函數(shù)返回值來(lái)傳遞動(dòng)態(tài)內(nèi)存這種方法雖然好用,但是常常有人把return語(yǔ)句用錯(cuò)了。這里強(qiáng)調(diào)不要用return語(yǔ)句返回指向“棧內(nèi)存”的指針,因?yàn)樵搩?nèi)存在函數(shù)結(jié)束時(shí)自動(dòng)消亡,見(jiàn)示例7-4-4。
char *GetString(void)
{
char p[] = "hello world";
return p; // 編譯器將提出警告
}
void Test4(void)
{
char *str = NULL;
str = GetString(); // str 的內(nèi)容是垃圾
cout<< str << endl;
}
示例7-4-4 return語(yǔ)句返回指向“棧內(nèi)存”的指針
用調(diào)試器逐步跟蹤Test4,發(fā)現(xiàn)執(zhí)行str = GetString語(yǔ)句后str不再是NULL指針,但是str的內(nèi)容不是“hello world”而是垃圾。
如果把示例7-4-4改寫(xiě)成示例7-4-5,會(huì)怎么樣?
char *GetString2(void)
{
char *p = "hello world";
return p;
}
void Test5(void)
{
char *str = NULL;
str = GetString2();
cout<< str << endl;
}
示例7-4-5 return語(yǔ)句返回常量字符串
函 數(shù)Test5運(yùn)行雖然不會(huì)出錯(cuò),但是函數(shù)GetString2的設(shè)計(jì)概念卻是錯(cuò)誤的。因?yàn)镚etString2內(nèi)的“hello world”是常量字符串,位于靜態(tài)存儲(chǔ)區(qū),它在程序生命期內(nèi)恒定不變。無(wú)論什么時(shí)候調(diào)用GetString2,它返回的始終是同一個(gè)“只讀”的內(nèi)存 塊。
---------------------------------------------------------------
看看林銳的《高質(zhì)量的C/C++編程》呀,上面講得很清楚的
---------------------------------------------------------------
對(duì)于1和2:
如果傳入的是一級(jí)指針S的話,
那么函數(shù)中將使用的是S的拷貝,
要改變S的值,只能傳入指向S的指針,即二級(jí)指針
---------------------------------------------------------------
程序1:
void myMalloc(char *s) //我想在函數(shù)中分配內(nèi)存,再返回
{
s=(char *) malloc(100); // s是值參, 函數(shù)返回后就回復(fù)傳遞前的數(shù)值,無(wú)法帶回分配的結(jié)果
}
這個(gè)和調(diào)用 void func (int i) {i=1;}; 一樣,退出函數(shù)體,i指復(fù)原的
程序2:void myMalloc(char **s)
{


*s=(char *) malloc(100); // 這個(gè)是可以的
}
等價(jià)于
void int func(int * pI) {*pI=1;} pI指針不變,指針指向的數(shù)據(jù)內(nèi)容是變化的
值參本身不變,但是值參指向的內(nèi)存的內(nèi)容發(fā)生了變化。
程序3:
void fun(int *p)
{
int b=100;
p=&b; // 等同于第一個(gè)問(wèn)題, b的地址并沒(méi)有被返回
}
程序4:
void fun(int *p)
{
*p=100; // okay
}
---------------------------------------------------------------
其實(shí)樓主的問(wèn)題和指針沒(méi)有多大關(guān)系,就是行參和值參的問(wèn)題
函數(shù)調(diào)用的時(shí)候,值參傳遞的是數(shù)值,是不會(huì)返回的
這個(gè)數(shù)值,在函數(shù)體內(nèi)部相當(dāng)于一個(gè)變量,是可以改變,但是這個(gè)改變是無(wú)法帶出函數(shù)體外部的
---------------------------------------------------------------
程序1:
void myMalloc(char *s) //我想在函數(shù)中分配內(nèi)存,再返回
{
s=(char *) malloc(100);//傳過(guò)來(lái)的是P所指的地址,并不是P的地址,所以改變S不會(huì)改變P
}
void main()
{
char *p=NULL;
myMalloc(p); //這里的p實(shí)際還是NULL,p的值沒(méi)有改變,為什么?
if(p) free(p);
}
程序2:void myMalloc(char **s)
{
*s=(char *) malloc(100);//S指向的是P的地址,所以改變了P所指的內(nèi)存單元.
}
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);////道理同第一個(gè)程序.
printf("%d/n",*q);
return 0;
}
結(jié)果為
10
10
程序4:
#include<stdio.h>
void fun(int *p)
{
*p=100;//參數(shù)P和實(shí)參P所指的內(nèi)存單元是相同的.所以改變了參數(shù)P的內(nèi)存單元內(nèi)容,就改變了實(shí)參
//的內(nèi)存單元內(nèi)容
}
main()
{
int a=10;
int *q;
q=&a;
printf("%d/n",*q);
fun(q);
printf("%d/n",*q);
return 0;
}
結(jié)果為
10
100
為什么?
---------------------------------------------------------------
void main()
{
char *p=NULL;
myMalloc(p); //這里的p實(shí)際還是NULL,p的值沒(méi)有改變,為什么?
if(p) free(p);
}
void myMalloc(char *s) //我想在函數(shù)中分配內(nèi)存,再返回
{
s=(char *) malloc(100);
}
myMalloc(p)的執(zhí)行過(guò)程:
分配一個(gè)臨時(shí)變量char *s,s的值等于p,也就是NULL,但是s占用的是與p不同的內(nèi)存空間。此后函數(shù)的執(zhí)行與p一點(diǎn)關(guān)系都沒(méi)有了!只是用p的值來(lái)初始化s。
然后s=(char *) malloc(100),把s的值賦成malloc的地址,對(duì)p的值沒(méi)有任何影響。p的值還是NULL。
注意指針變量只是一個(gè)特殊的變量,實(shí)際上它存的是整數(shù)值,但是它是內(nèi)存中的某個(gè)地址。通過(guò)它可以訪問(wèn)這個(gè)地址。
程序2:void myMalloc(char **s)
{
*s=(char *) malloc(100);
}
void main()
{
char *p=NULL;
myMalloc(&p); //這里的p可以得到正確的值了
if(p) free(p);
}
程序2是正確的,為什么呢?看一個(gè)執(zhí)行過(guò)程就知道了:
myMalloc(&p);將p的地址傳入函數(shù),假設(shè)存儲(chǔ)p變量的地址是0x5555,則0x5555這個(gè)地址存的是指針變量p的值,也就是Ox5555指向p。
調(diào)用的時(shí)候同樣分配一個(gè)臨時(shí)變量char **s,此時(shí)s 的值是&p的值也就是0x5555,但是s所占的空間是另外的空間,只不過(guò)它所指向的值是一個(gè)地址:Ox5555。
*s=(char *) malloc(100);這一句話的意思是將s所指向的值,也就是0x5555這個(gè)位置上的變量的值賦為(char *) malloc(100),而0x5555這個(gè)位置上存的是恰好是指針變量p,這樣p的值就變成了(char *) malloc(100)的值。即p的值是新分配的這塊內(nèi)存的起始地址。
這個(gè)問(wèn)題理解起來(lái)有點(diǎn)繞,關(guān)鍵是理解變量作函數(shù)形參調(diào)用的 時(shí)候都是要分配一個(gè)副本,不管是傳值還是傳址。傳入后就和形參沒(méi)有關(guān)系了,它不會(huì)改變形參的值。myMalloc(p)不會(huì)改變p的值,p的值當(dāng)然是 NULL,它只能改變p所指向的內(nèi)存地址的值。但是myMalloc(&p)為什么就可以了,它不會(huì)改變(&p)的值也不可能改變,但是 它可以改變(&p)所指向內(nèi)存地址的值,即p的值。
---------------------------------------------------------------
你要弄清楚的是指針變量和指針?biāo)傅淖兞浚赡苁且黄瑑?nèi)存)。
指針變量和普通變量一樣存儲(chǔ)的,

//////////////////////////////////////////////////////////////////


1.如果是函數(shù)內(nèi)進(jìn)行內(nèi)存申請(qǐng),很簡(jiǎn)單,標(biāo)準(zhǔn)用法就可以了:
test()
{
int *array;
array=(int *)malloc(sizeof(int)*10);//申請(qǐng)10*4 bytes,即10個(gè)單位的int內(nèi)存單元
}
注意,malloc使用簡(jiǎn)單,但是注意參數(shù)和返回值,參數(shù)是申請(qǐng)內(nèi)存的字節(jié)數(shù),多字節(jié)的類(lèi)型如int,short,float等需要乘上類(lèi)型字節(jié)數(shù),返回值是沒(méi)有定義類(lèi)型的指針,使用時(shí)需要自己指定。
2.使用一級(jí)指針實(shí)現(xiàn)內(nèi)存申請(qǐng),通過(guò)函數(shù)返回值帶出malloc的地址:
char *my_malloc(int m)
{
char *p;
p=malloc(m);
return p;
}
test()
{
char * buff=NULL; //指針如果在函數(shù)內(nèi)沒(méi)有賦值,注意開(kāi)始賦值為NULL
buff=my_malloc(10);
printf("buff adress is %x/n",buff);
free(buff);
}
3.使用二級(jí)指針實(shí)現(xiàn)內(nèi)存申請(qǐng),通過(guò)指針值傳遞:
void my_malloc1(char **p1)
{
*p1=(char *)malloc(100);
}
test()
{
char *buffer=NULL;
my_malloc1(&buffer);
printf("buffer adress is %x/n",buffer);
free(buffer);
}
小結(jié):一級(jí)指針和二級(jí)指針在做形參時(shí)的不同:指針用作形參,改變指針地址則值不能傳回,改變指針內(nèi)容而地址不變則值可以傳回。(特殊情況:改變指針地址采用返回值也可以傳回地址)
對(duì)于一級(jí)指針,做形參時(shí)傳入地址,如果函數(shù)只改變?cè)撝羔槂?nèi)容,OK,該指針可以正常返回,如果函數(shù)改變了指針地址,除非返回該指針,否則該指針不能正常返回,函數(shù)內(nèi)對(duì)指針的操作將無(wú)效。
對(duì)于二級(jí)指針,做形參時(shí)傳入地址(注意此時(shí)傳入的是二級(jí)指針的地址),如果改變?cè)摱?jí)指針地址(**p),對(duì)該指針的操作也將無(wú)效,但是改變二級(jí)指針的內(nèi)容(例如*p),則該二級(jí)指針可以正常返回。
總之,指針使用最關(guān)鍵的是弄清地址和內(nèi)容,指針做形參時(shí)只有改變其內(nèi)容時(shí)才能正常返回。
4.編程實(shí)例:
/*
date:20100823
file name:my_pointer.c
description:指針作為形參的值傳遞分析
result:
1.指針作為形參時(shí),如果只需要改變指針指向的值,可以使用一級(jí)指針,如果需要改變指針本身的地址
,則需要使用二級(jí)指針,相當(dāng)于改變的是一級(jí)指針指向的值。
2.指針作為形參時(shí),指針指向的內(nèi)容變化是可以帶回的,指針地址的變化是不可帶回的,即指針作為參
數(shù),其地址不可改變,否則形參就無(wú)法傳回實(shí)參的值。
*/
/*********************************************************************************/
//指針作為形參,指針指向的內(nèi)容改變,函數(shù)返回時(shí)這種變化是可以帶回的
void change(int *p)
{
*p+=5;
}
test1()
{
int a=1;
change(&a);
printf("After change a is %d/n",a); //結(jié)果為6
}
/*********************************************************************************/
//指針作為形參,指針本身的地址改變,函數(shù)返回時(shí)這種變化將無(wú)效
void my_malloc(char *pp,int num)
{
pp=(char *)malloc(num);
}
test2()
{
char *buf=NULL;
my_malloc(buf,100);
printf("After my_malloc buf adress is %x/n",buf); //函數(shù)返回后,buf的地址依然為NULL
strcpy(buf,"hello"); //這里會(huì)出錯(cuò),運(yùn)行出現(xiàn)段錯(cuò)誤,程序直接退出了,下面的輸
出也沒(méi)有了
puts(buf);
}
main()
{
test1();
//test2();
}

本站僅提供存儲(chǔ)服務(wù),所有內(nèi)容均由用戶發(fā)布,如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊舉報(bào)。
打開(kāi)APP,閱讀全文并永久保存 查看更多類(lèi)似文章
猜你喜歡
類(lèi)似文章
如何通過(guò)在函數(shù)外部的指針傳遞到函數(shù)內(nèi)部并且修改其內(nèi)容
C中內(nèi)存建立與釋放的函數(shù)
C 內(nèi)存管理詳解
C++內(nèi)存管理
C 知識(shí)點(diǎn)
指針參數(shù)是如何傳遞內(nèi)存的
更多類(lèi)似文章 >>
生活服務(wù)
熱點(diǎn)新聞
分享 收藏 導(dǎo)長(zhǎng)圖 關(guān)注 下載文章
綁定賬號(hào)成功
后續(xù)可登錄賬號(hào)暢享VIP特權(quán)!
如果VIP功能使用有故障,
可點(diǎn)擊這里聯(lián)系客服!

聯(lián)系客服