原文地址: https://www.cnblogs.com/AndyJee/p/4630153.html
C/C++精髓就是用門牌號(hào)(地址)找東西, 不需要把每個(gè)東西都放在房間里(memcpy)
C/C++精髓就是用門牌號(hào)(地址)找東西, 不需要把每個(gè)東西都放在房間里(memcpy)
C/C++精髓就是用門牌號(hào)(地址)找東西, 不需要把每個(gè)東西都放在房間里(memcpy)
主要內(nèi)容:
1馏慨、一級(jí)指針和二級(jí)指針
2、函數(shù)指針傳遞的例子
3、什么時(shí)候需要傳遞二級(jí)指針管挟?
4龄捡、二級(jí)指針在鏈表中的使用
1拣帽、一級(jí)指針和二級(jí)指針
一級(jí)指針:即我們一般說的指針践瓷,就是內(nèi)存地址耕驰;
二級(jí)指針:指向指針的指針炸卑,就是地址的地址既鞠;
如:
int a=1;
int *p=&a; // p為a變量的地址,通過*p可以得到a的值
int **q=&p; // q為p指針的地址盖文,通過**q可以得到a的值
2嘱蛋、函數(shù)指針傳遞的例子
程序1:
#include<stdio.h>
void fun(int *p){
int b=100;
p=&b;
}
int main(){
int a=10;
int *q;
q=&a;
printf("%d\n",*q);
fun(q);
printf("%d\n",*q);
return 0;
}
結(jié)果1:
10
10
程序2:
#include<stdio.h>
void fun(int **p){
int b=100;
*p=&b;
}
int main(){
int a=10;
int *q;
q=&a;
printf("%d\n",*q);
fun(&q);
printf("%d\n",*q);
return 0;
}
運(yùn)行結(jié)果:
10
100
程序3:
#include<stdio.h>
#include<stdlib.h>
void myMalloc(char *s){
s=(char*)malloc(100);
}
int main()
{
char *p=NULL;
myMalloc(p);
if(p==NULL)
printf("P is not changed!\n");
else{
printf("P has been changed!\n");
free(p);
}
return 0;
}
運(yùn)行結(jié)果:
P is not changed!
程序4:
#include<stdio.h>
#include<stdlib.h>
void myMalloc(char **s){
*s=(char*)malloc(100);
}
int main()
{
char *p=NULL;
myMalloc(&p);
if(p==NULL)
printf("P is not changed!\n");
else{
printf("P has been changed!\n");
free(p);
}
return 0;
}
運(yùn)行結(jié)果:
P has been changed!
3、什么時(shí)候需要傳遞二級(jí)指針五续?
通過上述例子洒敏,我們可以看到,在某些情況下疙驾,函數(shù)參數(shù)傳遞一級(jí)指針時(shí)凶伙,在函數(shù)體內(nèi)對(duì)指針做變動(dòng),也不會(huì)對(duì)原始指針產(chǎn)生變化它碎,而傳遞二級(jí)指針時(shí)函荣,則可以,這是為什么呢扳肛?
下面做簡(jiǎn)單的分析:
在函數(shù)傳遞參數(shù)時(shí),編譯器總會(huì)為每個(gè)函數(shù)參數(shù)制作一個(gè)副本套腹,即拷貝绪抛;
例如:
void fun(int *p),指針參數(shù)p的副本為_p电禀,編譯器使_p=p幢码,_p和p指向相同的內(nèi)存空間,如果在函數(shù)內(nèi)修改了_p所指向的內(nèi)容鞭呕,就會(huì)導(dǎo)致p的內(nèi)容也做相應(yīng)的改變蛤育;
但如果在函數(shù)內(nèi)_p申請(qǐng)了新的內(nèi)存空間或者指向其他內(nèi)存空間宛官,則_p指向了新的內(nèi)存空間,而p依舊指向原來的內(nèi)存空間瓦糕,因此函數(shù)返回后p還是原來的p底洗。
這樣的話,不但沒有實(shí)現(xiàn)功能咕娄,反而每次都申請(qǐng)新的內(nèi)存空間亥揖,而又得不到釋放,因?yàn)闆]有將該內(nèi)存空間的地址傳遞出來圣勒,容易造成內(nèi)存泄露费变。
void fun(int **p),如果函數(shù)參數(shù)是指針的地址圣贸,則可以通過該參數(shù)p將新分配或新指向的內(nèi)存地址傳遞出來挚歧,這樣就實(shí)現(xiàn)了有效的指針操作。
如果覺得二級(jí)指針比較難理解吁峻,也可以通過函數(shù)返回值的形式來傳遞動(dòng)態(tài)內(nèi)存()
如:
#include<stdio.h>
#include<stdlib.h>
char* myMalloc(){
char *s=(char*)malloc(100);
return s;
}
int main()
{
char *p=NULL;
p=myMalloc();
if(p==NULL)
printf("P is not changed!\n");
else{
printf("P has been changed\n");
free(p);
}
return 0;
}
知道了上述這些滑负,就不難理解上面四個(gè)小程序的執(zhí)行結(jié)果了。
4用含、二級(jí)指針在鏈表中的使用
在鏈表或者樹的操作中矮慕,也需要用到二級(jí)指針,
比如創(chuàng)建鏈表的頭指針:
在初始化鏈表函數(shù)中啄骇,傳入頭指針痴鳄,并在函數(shù)中為該指針分配空間,此時(shí)就應(yīng)該使用二級(jí)指針缸夹,如void initLinklist(Node **head)痪寻;
而在添加刪除結(jié)點(diǎn)的過程中,我們并沒有改變函數(shù)參數(shù)指針的指向明未,而是通過傳入的指針如Node *head槽华,找到要?jiǎng)h除結(jié)點(diǎn)的位置壹蔓,并未對(duì)該指針做改變趟妥,因此退出函數(shù)后,該指針無影響佣蓉。