*ポインタ [#b98431ab]
C/C++のポインタの概念を説明します。

#contents

**アドレス [#e2aa8599]
 int i = 10;

というコードがあるとします。
これがコンパイルされたとき、EXEのなかではどう表現されているのでしょうか?

変数の値は、実際にはメモリのどこかに保存されています。
そして「どこに保存されているか」というメモリの住所は、番号で表現されます。
上記のコードは、たとえば

 45450721番目のメモリに 10 を代入せよ

のようにコンパイルされます。
何番目のメモリを使うかは、コンパイラが勝手に決めてくれます。

C言語を使えば、このようにどの変数にどこのメモリを割り当てるかを
自動的に割り振ってくれるわけですね。

この、"何番目のメモリ" という番号のことを「アドレス」と呼びます。直訳すれば "住所" ですね。

**ポインタ [#ta60fe66]
さて、上記のコードにおいて、変数 i が何番目のメモリに格納されているかが知りたいときがあります。
用語を用いて言い換えれば、変数 i のアドレスが知りたいわけですね。

そういう時は &i と書けばおkです。上記の例では &i は 45450721 です。

C言語には、アドレスを格納するための特別な変数型があります。それを「ポインタ」と呼びます。
ポインタの宣言は

 int *p;

のように書きます。たとえば

 int i = 10;
 int *p = &i;

などとします。この p には、たとえば 45450721 などが格納されます。
この例では、p のことを「i へのポインタ」といいます。
「i へのポインタ」とは、"i のアドレスが格納されているポインタ"のことです。

では 45450721番目のメモリに入っている値(すなわち i に格納されている値)が知りたいときはどうするかというと

 printf("%d", *p);

と書きます。

*p のことを、「p が指す値」と呼びます。

**ポインタの宣言 [#n0e5a3dc]

 int i;

という宣言文は「i は int型である」と宣言しています。これと同じで

 int *p;

という宣言文は「*p は int型である」、もしくは「pとは、*p が int型になるような型の変数である」と宣言しています。

ちょっと複雑な例を考えましょう。intへのポインタを10個並べた配列 ap が欲しいときはどうすればよいでしょうか?

ap[index] はポインタですね。その指す値(int型)は、 *(ap[index]) で得られます。ですから ap の宣言は

 int *(ap[10]);

と書けばよいのです。

次に、intを10個並べた配列へのポインタ pa が欲しいときはどうすればよいでしょうか?

*pa は配列ですから、(*pa)[index] は int 型ですね。ですから

 int (*pa)[10];

と宣言すればよいです。

**関数の引数について [#h203a194]
*関数の引数について [#v202f321]
**値渡し [#i83f1e1e]

 #include <stdio.h>
 
 void func(int a)
 {
     a = 100;
 }
 
 int main()
 {
     int b = 1;
     func(b);
     printf("%d", b);
 }

というプログラムを実行すると、"1" と表示されます。決して "100" にはなりません。

具体的に追っていきましょう。&a は 45450721、&b は 6741 だとします。
main関数のなかでは、まず

 int b = 1;

で 6741番目のメモリが 1 になります。次に

 func(b);

では、45450721番目のメモリに 1 がコピーされて 
func の先頭にジャンプします。

func のなかで、45450721番目のメモリに 100 が代入されます。そうして

 printf("%d", b);

に戻ってきたとき、6741番目のメモリには何が入っているでしょう?

1 ですね。

このように、関数の引数には、呼び出し元の変数の値がコピーされ(「値渡し」)、
関数内部ではその''コピーされたものしかいじれません''。


**関数の引数にポインタを用いると [#oc238e97]

 #include <stdio.h>
 
 void func(int *p)
 {
     *p = 100;
 }
 
 int main()
 {
     int b = 1;
     func(&b);
     printf("%d", b);
 }

を最初から追っていきましょう。&p は 45450721、&b は 6741 だとします。
まず

 int b = 1;

で 6741番目のメモリが 1 になります。つぎに

 func(&b);

で、45450721番目のメモリに 6471 がコピーされて、funcの先頭へジャンプします。

funcのなかで、45450721番目のメモリに格納されている番号(6471番)の
メモリに 100 が代入されます。そうして

 printf("%d", b);

に戻ってきたとき、6741番目のメモリには 100 が入っています。
ですから、画面には "100" と表示されることになります。

このように、ポインタを関数の引数に用いると、
関数内で呼び出し元の変数をいじることができるようになります。

*配列 [#w189609e]

以下加筆します


トップ   新規 一覧 検索 最終更新   ヘルプ   最終更新のRSS