C/C++ 二級指針傳地址

原文地址: https://www.cnblogs.com/AndyJee/p/4630153.html

C/C++精髓就是用門牌號(地址)找東西, 不需要把每個東西都放在房間里(memcpy)
C/C++精髓就是用門牌號(地址)找東西, 不需要把每個東西都放在房間里(memcpy)
C/C++精髓就是用門牌號(地址)找東西, 不需要把每個東西都放在房間里(memcpy)

主要內(nèi)容:

1、一級指針和二級指針
2、函數(shù)指針傳遞的例子
3、什么時候需要傳遞二級指針?
4、二級指針在鏈表中的使用

1、一級指針和二級指針

一級指針:即我們一般說的指針,就是內(nèi)存地址;

二級指針:指向指針的指針,就是地址的地址;

如:

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;
}

運行結(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;
}

運行結(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;
}

運行結(jié)果:

P has been changed!

3、什么時候需要傳遞二級指針?

通過上述例子,我們可以看到,在某些情況下,函數(shù)參數(shù)傳遞一級指針時,在函數(shù)體內(nèi)對指針做變動,也不會對原始指針產(chǎn)生變化,而傳遞二級指針時,則可以,這是為什么呢?

\color{red}{在傳遞一級指針時,只有對指針所指向的內(nèi)存變量做操作才是有效的;}

\color{red}{在傳遞二級指針時,只有對指針的指向做改變才是有效的;}

下面做簡單的分析:

在函數(shù)傳遞參數(shù)時,編譯器總會為每個函數(shù)參數(shù)制作一個副本,即拷貝;

例如:

void fun(int *p),指針參數(shù)p的副本為_p,編譯器使_p=p,_p和p指向相同的內(nèi)存空間,如果在函數(shù)內(nèi)修改了_p所指向的內(nèi)容,就會導(dǎo)致p的內(nèi)容也做相應(yīng)的改變;
但如果在函數(shù)內(nèi)_p申請了新的內(nèi)存空間或者指向其他內(nèi)存空間,則_p指向了新的內(nèi)存空間,而p依舊指向原來的內(nèi)存空間,因此函數(shù)返回后p還是原來的p。
這樣的話,不但沒有實現(xiàn)功能,反而每次都申請新的內(nèi)存空間,而又得不到釋放,因為沒有將該內(nèi)存空間的地址傳遞出來,容易造成內(nèi)存泄露。
void fun(int **p),如果函數(shù)參數(shù)是指針的地址,則可以通過該參數(shù)p將新分配或新指向的內(nèi)存地址傳遞出來,這樣就實現(xiàn)了有效的指針操作。
如果覺得二級指針比較難理解,也可以通過函數(shù)返回值的形式來傳遞動態(tài)內(nèi)存\color{red}{切記不能返回棧內(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;
}

知道了上述這些,就不難理解上面四個小程序的執(zhí)行結(jié)果了。

4、二級指針在鏈表中的使用

在鏈表或者樹的操作中,也需要用到二級指針,

比如創(chuàng)建鏈表的頭指針:

在初始化鏈表函數(shù)中,傳入頭指針,并在函數(shù)中為該指針分配空間,此時就應(yīng)該使用二級指針,如void initLinklist(Node **head);

而在添加刪除結(jié)點的過程中,我們并沒有改變函數(shù)參數(shù)指針的指向,而是通過傳入的指針如Node *head,找到要刪除結(jié)點的位置,并未對該指針做改變,因此退出函數(shù)后,該指針無影響。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容