C語言二級指針與典型應用(1)

C語言二級指針與典型應用(1)

https://blog.csdn.net/ye1223/article/details/79674975

二級指針的定義:

A(即B的地址)是指向指針的指針,稱爲二級指針,用於存放二級指針的變量稱爲二級指針變量.本質:二級指針變量的值是一個地址。

一、概念

在如下的A指向B、B指向C的指向關係中:

首先,默認的編譯器是32位,即int型爲4字節。

C:"一段內容",可是是一個具體的常量、變量、或是用malloc(new)分配了一塊內存。C的起始地址是0x00000008。

B:一個指針變量,其中存放着C的地址。但是B也是變量,因此需要佔空間,所以B也有地址,B的起始地址是0x00000004。因爲B中存放的是C的地址,所以B裏面的內容就是0x00000008。

備註:當C是一個局部 非static變量或是數組時,系統是在棧中爲變量分配內存;如果是採用malloc,則是在堆中分配內存。當B是一個局部 非static指針變量時,系統是在棧中爲變量分配內存,即B的起始地址是在棧中;但並不限制指針所指向對象的內存位置,即可以指向在堆中的變量,如malloc分配的數組變量。

[cpp] view plain copy

  1. B= 0x00000008;  //B的值   
  2. *B = "一段內容";  //B取內容,也就是B指針指向的C的值  
  3. &B = 0x00000004;  //B取地址,B的地址是0x00000004  

A是二級指針變量,其中存放着B的地址0x00000004。A也有地址,是0x00000000;

[cpp] view plain copy

  1. *A = B= 0x00000008;  //A取內容就是B的內容   
  2. **A = *B = "一段內容";  //B取內容,也就是B指針指向的C的值  
  3. A = &B = 0x00000004;  //A存的是B的地址,B的地址是0x00000004  
  4. &A = 0x00000000;  //A取地址  

 

二、典型使用之一

二級指針作爲函數參數的作用:在函數外部定義一個指針p,在函數內給指針賦值,函數結束後對指針p生效,那麼我們就需要二級指針。

看看下面一段代碼:有兩個變量a,b,指針q,q指向a,我們想讓q指向b,在函數裏面實現。

1.先看看一級指針的實現


 
  1. #include <stdio.h>

  2. #include <stdlib.h>

  3.  
  4. int a= 10;

  5. int b = 100;

  6. int *q = NULL;

  7.  
  8. void func(int *p)

  9. {

  10. printf("func:&p=%d,p=%d\n",&p,p); //note:3

  11. p = &b;

  12. printf("func:&p=%d,p=%d\n",&p,p); //note:4

  13. }

  14.  
  15.  
  16. int main()

  17. {

  18. printf("&a=%d,&b=%d,&q=%d\n",&a,&b,&q); //note:1

  19. q = &a;

  20. printf("*q=%d,q=%d,&q=%d\n",*q,q,&q); //note:2

  21. func(q);

  22. printf("*q=%d,q=%d,&q=%d\n",*q,q,&q); //note:5

  23.  
  24. return 0;

  25. }

輸出:

note:1->a,b,q都有一個地址.

note:2->q指向a.

note:3->我們發現參數p的地址和q的地址並不相同。

note:4->p重新指向b.

note:5->退出函數,p的修改並不會對q造成影響。

結論:

(1)p的地址和q的地址不同的原因:形參p在函數func被調用時作爲臨時變量,系統會在棧中爲p分配一個獨立內存,而q作爲全局變量,是在靜態內存區分配的內存(參見文檔:《C/C++程序運行時的內存分配》);因此p和q具有不同的地址。但是同時注意:p和q的地址不同,但是值(即保存的數據)相同,均是變量a的地址。

(2)C語言中,實參向形參的數據傳遞分爲3種:值傳遞、地址傳遞和引用傳遞。此處屬於地址傳遞(即實參和形參的均是某變量的地址)。因此,p和q均指向a,對*p進行操作,即對a進行操作。但是注意:不管對p進行何種操作,均不會改變q的值和q的地址(因爲屬於不同的變量),最多隻會改變q指向的變量a的值。

(3)如果想通過操作指針p,對a和q均進行修改,那就需要用到二級指針。

2.二級指針操作

#include <stdio.h>
#include <stdlib.h>

int a= 10;
int b = 100;
int *q = NULL;

void func(int **p)
{
    printf("func:\tp=%d\t&p=%d\n",p,&p);     //note:3
    *p = &b;
    printf("func:\tp=%d\t&p=%d\n",p,&p);     //note:4
}

int main()
{
    printf("&a=%d\t&b=%d\t&q=%d\n",&a,&b,&q);   //note:1
    q = &a;
    printf("*q=%d\tq=%d\t&q=%d\n",*q,q,&q);     //note:2
    func(q);
    printf("*q=%d\tq=%d\t&q=%d\n",*q,q,&q);     //note:5

    return 0;
}

結論::

(1)p爲二級指針,保存的是q的地址。參見上:p和q保存在不同的內存區域。p=&q,因此當進行*p=&b時,即進行的是q=&b,改變了指針q的指向。

例子: 

void  my_malloc(char **s)    
{    
    *s=(char*)malloc(100);    
}    
   
void  main()    
{    
    char  *p=NULL;    
    my_malloc(&p);  
    free(p);
    p=NULL;           
} 

函數分析:

(1)目的:通過調用子函數,爲主函數指針分配一塊內存空間;

在調用my_malloc時,實參值爲&p,即指針p的地址;my_malloc執行時,分配臨時變量s=&p; *s=(char*)malloc(100)操作等同於:p=(char*)malloc(100);即通過調用子函數,爲主函數指針分配一塊內存空間。

(2)注意:如果malloc函數被調用,則後續函數中一定需要有free將對應的內存釋放,否則可能導致內存泄露;當free(p)後,需要讓p=NULL,否則指針p會成爲野指針!

文章部分參考:http://blog.csdn.net/majianfei1023/article/details/46629065

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章