針の針を徹底的に仕上げる!

5145 ワード

一.ポインタの概念を振り返る:
今日はまた別のポインタアドレスを指すポインタを勉強します.まずポインタの概念を振り返ってみましょう. 
次のように変数を説明します.
short int i; 
char a; 
short int * pi; 
次の図に示すように、プログラムはメモリのあるアドレス空間に各変数のために空間を開きます. 
メモリアドレス→6 7 8 9 10 11 12 13 15
------------------------------------------------------------------------------------- 
…  |     |      |      |      |      |       |      |      |      |    
------------------------------------------------------------------------------------- 
     |short int i |char a|      |short int * pi| 
図に示すように、
i変数はメモリアドレス5の位置にあり、2バイトを占める. 
a変数はメモリアドレス7の位置にあり、1バイトを占める. 
pi変数はメモリアドレス9の位置にあり、2バイトを占める.(注:piはポインタで、ここではポインタの幅は2バイトしかなく、32ビットシステムは4バイトです)
次に、次のように割り当てます.
i=50; 
pi=&i; 
上の2つの文の値を割り当てると、変数のメモリマッピングは次のようになります.
メモリアドレス→6 7 8 9 10 11 12 13 15
-------------------------------------------------------------------------------------- 
…  |    50      |      |      |    6         |      |      |       |    
-------------------------------------------------------------------------------------- 
     |short int i |char a|      |short int * pi| 
いいえ:短いポインタ変数piの値は6で、I変数のメモリ開始アドレスです.したがって,このとき*piに対して読み書き操作を行うと,実はi変数に対する読み書き操作である.次のようになります.
*pi=5;//I=5に等しい. 
本シリーズの第2編を見返すことができます.そこにはもっと詳しい解説があります. 
  
二.ポインタのアドレスと別のポインタのアドレスを指すポインタ
前節では、piのメモリ開始アドレスが10であるように、ポインタ変数自体も他の変数と同様にメモリアドレスに存在することを示した.同様に、あるポインタをこのアドレスに向けることもできます. 
次のコードを見てください.
short int * * ppi;//ポインタを指すポインタです.*番号が2つあることに注意してください.
ppi=π 
  
short int**ppi;——short int*タイプのポインタ変数を格納(または指向)するためのアドレスであるポインタ変数ppiが示されている.
第二句:&piそれはpiのアドレスを取ることで、ppi=πpiのアドレスをppiに割り当てたのです.アドレス値10をppiに割り当てる.次の図を示します.
メモリアドレス→6 7 8 9 10 11 12 13 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 find 1(char array[],char search,char*pi)
要求:この関数パラメータの配列arrayは0値で終わる文字列であり、文字列arrayで文字を検索するのはパラメータsearchの文字であることが要求される.見つかった場合、関数は3番目のパラメータ(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 (“   !
”);//1. } else { printf(“ ,p=%d”,p); // } }

分析:
上のコードは、何を出力すると思いますか? 
実行してみます. 
ああ!どのように出力したのは:見つかりませんでした! 
見つけたのではなく、....... 
a値が「d」なのにstr文字列の4番目の文字が「d」なので、見つかるはずですよ. 
関数定義を参照:void find 1(char[]array,char search,char*pa)
呼び出し先を見てください:find 1(str,a,p); 
私の5編目の分析方法によれば、関数呼び出し時に各パラメータに対して暗黙の付与操作を行う. 
呼び出し全体は次のとおりです.
    
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値の修正です. 
自分で調整してください. 
修正したプログラムで必要な機能を完成させることができます.