徹底搞定C指針——指針的指針

標  題: 徹底搞定C指針---指向指針的指針(轉) 

一. 回顧指針概念: 
今天我們又要學習一個叫做指向另一指針地址的指針。讓我們先回顧一下指針的概念吧! 
當我們程序如下申明變量: 
short int i; 
char a; 
short int * pi; 
程序會在內存某地址空間上爲各變量開闢空間,如下圖所示。 
內存地址→6     7      8     9     10     11    12    13     14    15 
------------------------------------------------------------------------------------- 
…  |     |      |      |      |      |       |      |      |      |    
------------------------------------------------------------------------------------- 
     |short int i |char a|      |short int * pi| 
圖中所示中可看出: 
i 變量在內存地址5的位置,佔兩個字節。 
a變量在內存地址7的位置,佔一個字節。 
pi變量在內存地址9的位置,佔兩個字節。(注:pi 是指針,我這裏指針的寬度只有兩個字節,32位系統是四個字節) 
接下來如下賦值: 
i=50; 
pi=&i; 
經過上在兩句的賦值,變量的內存映象如下: 
內存地址→6     7      8     9     10     11    12    13      14     15 
-------------------------------------------------------------------------------------- 
…  |    50      |      |      |    6         |      |      |       |    
-------------------------------------------------------------------------------------- 
     |short int i |char a|      |short int * pi| 
看到沒有:短整型指針變量pi的值爲6,它就是I變量的內存起始地址。所以,這時當我們對*pi進行讀寫操作時,其實就是對i變量的讀寫操作。如: 
*pi=5;   //就是等價於I=5; 
你可以回看本系列的第二篇,那裏有更加詳細的解說。 
  
二. 指針的地址與指向另一指針地址的指針 
在上一節中,我們看到,指針變量本身與其它變量一樣也是在某個內存地址中的,如pi的內存起始地址是10。同樣的,我們也可能讓某個指針指向這個地址。 
看下面代碼: 
short int * * ppi;    //這是一個指向指針的指針,注意有兩個*號 
ppi=π 
  
第一句:short int * * ppi;——申明瞭一個指針變量ppi,這個ppi是用來存儲(或稱指向)一個short int * 類型指針變量的地址。 
第二句:&pi那就是取pi的地址,ppi=π就是把pi的地址賦給了ppi。即將地址值10賦值給ppi。如下圖: 
內存地址→6     7      8     9     10     11    12    13       14    15 
------------------------------------------------------------------------------------ 
…  |    50     |      |      |      6       |       10      |      |    
------------------------------------------------------------------------------------ 
     |short int i|char a|      |short int * pi|short int ** ppi| 
從圖中看出,指針變量ppi的內容就是指針變量pi的起始地址。於是…… 
ppi的值是多少呢?——10。 
*ppi的值是多少呢?——6,即pi的值。 
**ppi的值是多少呢?——50,即I的值,也是*pi的值。 
呵呵!不用我說太多了,我相信你應明白這種指針了吧! 
  
三. 一個應用實例 
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值的修改。 
你自行去調試。 
經過修改後的程序就可以完成所要的功能了。 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章