第6講 ポインタの学習

第7話 ポインタのポインタによる2次元配列参照

解答例
#pragma endregion
   private: System::Void button1_Click(System::Object^ sender, System::EventArgs^ e) {
           //ポインタのポインタの宣言
           int** a;
           //ポインタの宣言
           int* b;
           //1次元配列の宣言
           int c[5];
           //整数型変数の宣言
           int i,j;

           //1次元配列にデータを入れる
           for(i=0;i<5;i++)c[i]=i+1;

           //配列のアドレスをポインタに代入
           b=c;

           //ポインタのポインタの初期化
           a=(int** )malloc(20);

           //ポインタのポインタにbのアドレスを代入
           a=&b;

           //文字型変数の宣言と初期化
           String^ w=L"";

           //ポインタを使ってlable1に配列のデータを表示
           for(i=0;i<5;i++)w+=(*(b+i)).ToString()+L" ";
           label1->Text=w;

           //ポインタのポインタを使ってlable2に配列のデータを表示
           w=L"";   //これを忘れると前のデータが残ってしまう。
           for(i=0;i<5;i++)w+=(*(*a+i)).ToString()+L" ";
           label2->Text=w;

           //配列ポインタの宣言
           int *d[4];
           //配列ポインタの初期化
           for(i=0;i<4;i++)d[i]=(int *)malloc(20);

           //配列ポインタ(2次元配列)へのデータの代入
           for(i=0;i<4;i++){
             for(j=0;j<5;j++){
               d[i][j]=rand()%10;        
             }
           }                   //ここの4行はfor(i=0;i<4;i++)for(j=0;j<5;j++)d[i][j]=rand()%10; でもよい。

           //配列ポインタのアドレスをポインタのポインタに代入      
           a=d;

           //ポインタのポインタによる2次元配列データの表示
           w=L"";  //これを忘れると前のデータが残ってしまう。
           for(i=0;i<4;i++){
             for(j=0;j<5;j++){
               w+=a[i][j]+L" ";  //ここのw+=a[i][j]+L" "; はw=w+a[i][j]+L" "; と同じ
             }
             w+=L"\n";       //ここのw+=L"\n"; はw=w+L"\n"; と同じ
           }
           label3->Text=w;
         }
};
}

解説
w=L""; を忘れると、Label2が
ポインタのポインタ(説明のためにLabel3を外してある。)
となってしまいます。それは前のデータ2次元配列の参照が残っているからです。
ですから前のデータをクリアするためにw=L""; を入れなければならないのです。

C言語では、w=w+a; を w+=a; と簡略表現することもできます。
本講座では、わかりやすさを優先して、なるべく簡略表現を使わないようにしています。
for(i=0;i<4;i++)for(j=0;j<5;j++)d[i][j]=rand()%10; も
for(i=0;i<4;i++){
  for(j=0;j<5;j++){
    d[i][j]=rand()%10;        
  }
}      
の簡略表現です。for文とif文は命令がひとつしかないときは、{}を省略できるのです。

rand()%10; は10以下の整数をランダムに発生させるものです。

前話でも解説しましたが、配列ポインタ(配列のポインタ)int *d[4]; 
があたかも2次元配列のようにd[i][j]として使えている点に注目して下さい。
もともとが、配列ポインタですからd[i][j]*(d[i]+j)*(*(d+i)+j)ともできます。
また、a=d;とするとポインタのポインタaもa[i][j]のようにあたかも2次元配列であるように扱えることにもスポットを当ててください。
もちろん、aはポインタのポインタですからa[i][j]*(*(a+i)+j)*(a[i]+j)とすることもできます。
逆に、
int a[5];
int b[10][8];
等と配列を宣言したとき、a[i]は*(a+i)と、b[i][j]は*(*(b+i)+j)あるいは*(b[i]+j)と表現できます。
基本的にポインタは配列に似ているのですが、配列より大きな適応範囲・応用範囲をもっています。


ポインタaは、箱の中身ではなく箱のラベルともいうべきメモリアドレスを扱いますが、
*aによって、箱の中身も参照して扱うことができるのです。
ここにポインタの強さと難しさがあります。

以上で、ポインタの学習は終わりにします。
といって、関数のところで関数ポインタを再び学習することになりますが。
関数の学習に入る前にfor文以外のループ文を見ていきましょう。




第6話へ 第7講第1話へ


025


vc++講義へ
vb講義へ
VB講義基礎へ
初心者のための世界で一番わかりやすいVisual Basic入門基礎講座へ



数学研究室に戻る