徹底搞定C指針---指向指針的指針指向指針的指針(轉載)


  C及C++語言中,最讓人頭疼的就是指針問題了,這章主要介紹一下關於指針及指針的指針的概念。區分*p與**p的區別。

(1)、指針概念

當我們程序如下申明變量:
short int i;
char a;
short int * pi;
程序會在內存某地址空間上為各變量開辟空間,如下圖所示。
內存地址   5    6     7      8     9     10     11    12   13   14    
    -------------------------------------------------------------------------------------
    …  |     |      |      |      |      |       |      |      |      |    
    ------------------------------------------------------------------------------------- 
         |short int i  |  |char a|   |short int * pi|
圖中所示中可看出:
i 變量在內存地址5的位置,占兩個字節。
a變量在內存地址8的位置,占一個字節。
pi變量在內存地址10的位置,占兩個字節。(注:pi 是指針,我這里指針的寬度只有兩個字節,32位系統是四個字節)
接下來如下賦值:
i=50;
pi=&i;
經過上在兩句的賦值,變量的內存映象如下:
內存地址   5    6     7      8     9     10     11    12   13   14    
    -------------------------------------------------------------------------------------
    …  |     50     |      |      |      |       5      |      |      |    
    ------------------------------------------------------------------------------------- 
         |short int i  |    |char a|   |short int * pi|

看到沒有:短整型指針變量pi的值為5,它就是i變量的內存起始地址。所以,這時當我們對*pi進行讀寫操作時,其實就是對i變量的讀寫操作。如:
*pi=5;   //就是等價於i=5; 
 
(2)、指針的地址與指向另一指針地址的指針
在上一節中,我們看到,指針變量本身與其它變量一樣也是在某個內存地址中的,如pi的內存起始地址是10。同樣的,我們也可能讓某個指針指向這個地址。
看下面代碼:
short int * * ppi;    //這是一個指向指針的指針,注意有兩個*號
ppi=π
  
第一句:short int * * ppi;——申明了一個指針變量ppi,這個ppi是用來存儲(或稱指向)一個short int * 類型指針變量的地址。
第二句:&pi那就是取pi的地址,ppi=π就是把pi的地址賦給了ppi。即將地址值10賦值給ppi。如下圖:

內存地址   5    6     7      8     9     10     11    12   13   14    
    -------------------------------------------------------------------------------------
    …  |     50     |      |      |      |       5     |      |     10    
    ------------------------------------------------------------------------------------- 
         |short int i  |   |char a|    |short int * pi|  |short int ** ppi|
從圖中看出,指針變量ppi的內容就是指針變量pi的起始地址。於是……
ppi的值是多少呢?——13。
*ppi的值是多少呢?——10,即pi的值。
**ppi的值是多少呢?——50,即I的值,也是*pi的值。
呵呵!不用我說太多了,我相信你應明白這種指針了吧! 
  
(3)、 一個應用實例
1. 設計一個函數:void find1(char array[], char search, char * pi)
要求:這個函數參數中的數組array是以0值為結束的字符串,要求在字符串array中查找字符是參數search里的字符。如果找到,函數通過第三個參數(pa)返回值為array字符串中第一個找到的字符的地址。如果沒找到,則為pa為0。
設計:依題意,實現代碼如下。
void find1(char [] array, char search, char * pa)
{
    int i;
    for (i=0;*(array+i)!=0;i++)
    {
       if (*(array+i)==search)
       {
         pa=array+i
         break;
       }
       else if (*(array+i)==0)
       {
         pa=0;
         break;
       }
    }
}
你覺得這個函數能實現所要求的功能嗎?
調試:
我下面調用這個函數試試。
void main()
{
   char str[]={“afsdfsdfdf\0”};  //待查找的字符串
   char a=’d’;   //設置要查找的字符
   char * p=0;  //如果查找到后指針p將指向字符串中查找到的第一個字符的地址。
   find1(str,a,p);  //調用函數以實現所要操作。
   if (0==p )
   {
      printf (“沒找到!\n”);//1.如果沒找到則輸出此句
   }
   else
   {
      printf(“找到了,p=%d”,p);  //如果找到則輸出此句
   }
}
分析:
上面代碼,你認為會是輸出什么呢?
運行試試。
唉!怎么輸出的是:沒有找到!
而不是:找到了,……。
明明a值為’d’,而str字符串的第四個字符是’d’,應該找得到呀!
再看函數定義處:void find1(char [] array, char search, char * pa)
看調用處:find1(str,a,p);
函數調用時會對每一個參數進行一個隱含的賦值操作。 整個調用如下:
    array=str;
    search=a;
    pa=p;    //請注意:以上三句是調用時隱含的動作。
    int i;
    for (i=0;*(array+i)!=0;i++)
    {
       if (*(array+i)==search)
       {
         pa=array+i
         break;
       }
       else if (*(array+i)==0)
       {
         pa=0;
         break;
       }
    }
哦!參數pa與參數search的傳遞並沒有什么不同,都是值傳遞嘛(小語:地址傳遞其實就是地址值傳遞嘛)!所以對形參變量pa值(當然值是一個地址值)的修改並不會改變實參變量p值,因此p的值並沒有改變(即p的指向並沒有被改變)。
修正:
void find2(char [] array, char search, char ** ppa)
{
    int i;
    for (i=0;*(array+i)!=0;i++)
    {
       if (*(array+i)==search)
       {
         *ppa=array+i
         break;
       }
       else if (*(array+i)==0)
       {
         *ppa=0;
         break;
       }
    }
}
主函數的調用處改如下:
   find2(str,a,&p);  //調用函數以實現所要操作。
再分析:
這樣調用函數時的整個操作變成如下:
    array=str;
    search=a;
    ppa=&p;    //請注意:以上三句是調用時隱含的動作。
    int i;
    for (i=0;*(array+i)!=0;i++)
    {
       if (*(array+i)==search)
       {
         *ppa=array+i
         break;
       }
       else if (*(array+i)==0)
       {
         *ppa=0;
         break;
       }
    }
看明白了嗎?
ppa指向指針p的地址。
對*ppa的修改就是對p值的修改。 
經過修改后的程序就可以完成所要的功能了。


注意!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。



 
粤ICP备14056181号  © 2014-2021 ITdaan.com