c語言的一級指針和二級指針做爲函數參數,鏈表,malloc中的分配等等總結

原文網址:https://blog.csdn.net/u011123091/article/details/82055257小程序

c語言的一級指針和二級指針做爲函數參數,鏈表,malloc中的分配等等總結主要內容:ide

一、一級指針和二級指針函數

二、函數指針傳遞的例子.net

三、何時須要傳遞二級指針?3d

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

一、一級指針和二級指針
一級指針:即咱們通常說的指針,就是內存地址;code

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

如:內存

int a=1;

int *p=&a;  // p爲a變量的地址,經過*p能夠獲得a的值

int **q=&p;   // q爲p指針的地址,經過**q能夠獲得a的值

二、函數指針傳遞的例子
程序1:get

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

}

運行結果:

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;

}

運行結果:

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;

}

運行結果:

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;

}

運行結果:

P has been changed!

三、何時須要傳遞二級指針?

經過上述例子,咱們能夠看到,在某些狀況下,函數參數傳遞一級指針時,在函數體內對指針作變更,也不會對原始指針產生變化,而傳遞二級指針時,則能夠,這是爲何呢?

在傳遞一級指針時,只有對指針所指向的內存變量作操做纔是有效的;

在傳遞二級指針時,只有對指針的指向作改變纔是有效的;

下面作簡單的分析:

在函數傳遞參數時,編譯器總會爲每一個函數參數製做一個副本,即拷貝;

例如:

void fun(int *p),指針參數p的副本爲_p,編譯器使_p=p,_p和p指向相同的內存空間,若是在函數內修改了_p所指向的內容,就會致使p的內容也作相應的改變;

但若是在函數內_p申請了新的內存空間或者指向其餘內存空間,則_p指向了新的內存空間,而p依舊指向原來的內存空間,所以函數返回後p仍是原來的p。

這樣的話,不但沒有實現功能,反而每次都申請新的內存空間,而又得不到釋放,由於沒有將該內存空間的地址傳遞出來,容易形成內存泄露。

void fun(int **p),若是函數參數是指針的地址,則能夠經過該參數p將新分配或新指向的內存地址傳遞出來,這樣就實現了有效的指針操做。

若是以爲二級指針比較難理解,也能夠經過函數返回值的形式來傳遞動態內存(切記不能返回棧內存),如:

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

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

四、二級指針在鏈表中的使用
在鏈表或者樹的操做中,也須要用到二級指針,

好比建立鏈表的頭指針:

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

而在添加刪除結點的過程當中,咱們並無改變函數參數指針的指向,而是經過傳入的指針如Node *head,找到要刪除結點的位置,並未對該指針作改變,所以退出函數後,該指針無影響。

相關文章
相關標籤/搜索