第6講 ポインタの学習
第5話 ポインタのポインタの簡単な演習
では具体的に見ていきましょう。
次のようなForm1をつくり、
次のようにコーティングしてみましょう。
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
int** a;
int* b;
int c;
c=5;
b=&c;
a=(int** )malloc;
*a=b;
label1->Text=(*b).ToString();
label2->Text=(**a).ToString();
}
};
}
実行結果は、
で同じです。
b=&c; と *a=b; によって、
cのアドレスがbと*aに入っています。
ですから、*a=b=&cです。
今回は入れていませんが、bのアドレスも&bもaに代入することもできます。
a=&b;
プログラミングは次のように変更しても同じです。
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
int** a;
int* b;
int c;
c=5;
b=&c;
a=(int** )malloc;
a=&b;
label1->Text=(*b).ToString();
label2->Text=(**a).ToString();
}
};
}
これはどういうことでしょうか。
int** a;と宣言すると、aと*aと**aの3つを同時に操作できるようになります。
第2話で int *a; と宣言するとポインタ変数aと普通の変数*aを同時に宣言したことになると説明しましたが、
これは比喩的な表現で、もう少し正確に表現するとaから*aを参照できるようになるということです。
この表現を使うと、ポインタのポインタaから*aと**aと参照できます。
int** a; としたとき3つの変数を宣言しているのではなく、宣言しているのはあくまでaのみです。
しかし、*aと**aを見ることができるようになります。
aには変数bのアドレス&b
(0100000 こう書いているのはあくまで仮のアドレスです。
実際には、こんな単純な割り振りはしませんし、16進数表現です。
わかりやすさ優先でこう表現しています。)
が入っています。*aはそのアドレスのメモリーに収納されているデータを参照しなさい、という命令なのです。
さらに、bにはcのアドレス00000000が入っています。
**aは、そのアドレスのメモリーにはいっているデータ内容を参照しなさいということなのです。
結果的には、aから*aであるbと**aであるcを参照することができます。
*aとはaに収納されているアドレスのメモリ(箱)の中身を見なさいということなのです。
上の例では、aは01000000です。*aとは、01000000というアドレスのメモリの中身ということで00000000が参照されます。
同様にして、**aは*aに収納されているアドレスのメモリ(箱)の中身を見なさいということで5が参照されるのです。
図は次のように書き直した方がわかりやすいでしょうか。
結局aから*aと**aが参照できています。
頭が混乱してしまいますが、ポインタを理解するとC言語の仕組みが見えてきます。
魅力があると同時にC言語を難しくしている、と第1話でいった意味が少し見えてきたのではないでしょうか。
最後に課題を出してこの話を閉じましょう。
コード
#pragma endregion
private: System::Void button1_Click(System::Object^ sender, System::EventArgs^
e) {
int** a;
int* b;
int c;
c=5;
b=&c;
a=(int** )malloc;
a=&b;
label1->Text=(*b).ToString();
label2->Text=(**a).ToString();
}
};
}
少し変更して、実行結果が
int c; は配列int c[5]; としてください。
label1もlabel2もfor文で実現してください。
今回と同様にlabel1には*bをlabel2には*aを利用してください。
尚、bに入れストアドレスを代入するときは、
b=&(c[0]); または b=c; です。
第4話へ 第6話へ