2012年6月12日

すーさんのプログラミング講座!ポインタ編

C言語で壁と言われているポインタについての解説をみんな大好きすーさんが解説してくれました!
6
@mable_moc

@JA1TYE ポインタ教えてください…

2012-06-12 22:39:08
JA1TYE/Ryota Suzuki @JA1TYE

@mable_moc んー,int *hoge;みたいに宣言した変数は,int型の変数(今回はint piyoと仮定)がどこにあるか,っていう情報を記憶できるんですね.たとえばhoge=&piyo;としてやると,hogeにはpiyoのある場所(メモリアドレス)が記憶されます.

2012-06-12 22:45:06
JA1TYE/Ryota Suzuki @JA1TYE

@mable_moc でもって,*hogeってやるとhogeが記憶してる場所にしまってあるデータを取り出すことが出来るのです.今回は&piyoが記憶されているので,*hogeと書くとpiyoの中身を取り出すことができます.

2012-06-12 22:46:57
JA1TYE/Ryota Suzuki @JA1TYE

んー,ポインタは他人に説明するのが難しい.

2012-06-12 22:47:38
@mable_moc

@JA1TYE そのアドレスという概念がいまいち… C言語でおすすめの初学者向けの本とかないでしょうか?

2012-06-12 22:47:38
JA1TYE/Ryota Suzuki @JA1TYE

@mable_moc 私は正直な所高校の教科書がおすすめなのですが,「猫でもわかるC言語」がおすすめだと正義のハッカーが申しております.

2012-06-12 22:48:34
@mable_moc

@JA1TYE あっちょっとわかった気がする

2012-06-12 22:50:02
JA1TYE/Ryota Suzuki @JA1TYE

@mable_moc 変数ってのはコンピュータ内の引き出しの1つ(メモリ領域の1つ)に対してわかりやすい名前をつけたものなのですが,実際の所コンピュータは変数名とは別にすべての引き出しに通し番号を振って管理しているんですね.その通し番号をアドレスっていいます.

2012-06-12 22:50:32
JA1TYE/Ryota Suzuki @JA1TYE

まず,前提知識として,変数はコンピュータ内のデータの入れ物,とよく例えられますね.ここでは入れ物,という考え方を一歩進めて,大量の引き出しがあるタンスの1つの引き出しに,名前をつけたものが1つの変数,と考えることにします.

2012-06-12 22:52:23
JA1TYE/Ryota Suzuki @JA1TYE

実際の所,普通にものを出し入れする分には引き出しにつけた名前でやりとりすればいいのですが,実はコンピュータは変数の名前でデータ(引き出しの中身)を管理しているのではなく,全てのタンスに対して振った通し番号でデータを管理しています.

2012-06-12 22:54:16
JA1TYE/Ryota Suzuki @JA1TYE

この通し番号のことを一般に「番地」とか「アドレス」とか言います.変数名とアドレスの対応関係は,変数が宣言された時に適当に決定されます.そして,C言語では変数名からそれに対応しているアドレスを知るために,&という記号を使います.

2012-06-12 22:57:34
JA1TYE/Ryota Suzuki @JA1TYE

&hoge;とかするのは,変数名hogeに対応するアドレスを取り出しているわけです.さて,ポインタに話を戻しましょう.ポインタ変数(例: int *ptr)は,この「アドレス」を記憶するための特別な引き出しです.

2012-06-12 22:59:18
JA1TYE/Ryota Suzuki @JA1TYE

この特別な引き出しには,アドレスをしまうことができます.アドレスをしまう時は,ポインタ変数がint *ptrであったとき,ptr=&hoge;のようにして入れます.宣言の時にあった*マークはどこへ行ってしまったのでしょう.

2012-06-12 23:01:14
JA1TYE/Ryota Suzuki @JA1TYE

不思議な事に,この特別な引き出しに*をつけて開けてやると,さっき中に入れたアドレスが見えるのではなく,さっき中に入れたアドレスが振ってある引き出しの中身があたかも今開けた引き出しに入っているように見えるのです.

2012-06-12 23:03:24
JA1TYE/Ryota Suzuki @JA1TYE

当然,今開けた引き出しの中身(つまり,さっき中に入れたアドレスが振ってある引き出しの中身)を書き換えると,さっき中に入れたアドレスが振られている引き出しの中身も書き換わります.

2012-06-12 23:05:38
JA1TYE/Ryota Suzuki @JA1TYE

特別な引き出しのパワーでさっき中に入れたアドレスが振られている引き出しの中身を呼び寄せているだけで,中身の実体は1つしか存在しないのです.

2012-06-12 23:06:53
JA1TYE/Ryota Suzuki @JA1TYE

さて,ポインタが特別な引き出し,ということは理解いただけたでしょうか.今度はいつ使うのか?です.全部の引き出しをいつでも開けられるのなら,別にこんな回りくどいことをしないで,直接所望の引き出しを開ければ済むはずです.

2012-06-12 23:08:04
ゅずファン @kazh98

@JA1TYE いや,ポインタ難しいなと思った。

2012-06-12 23:08:53
JA1TYE/Ryota Suzuki @JA1TYE

実は,C言語において,各関数の中でつけた引き出しの名前は,各関数の中でしか通用しません.つまりローカルルールなんですね.なので,各関数で宣言した変数を「ローカル変数」と呼びます.このローカルルールのせいで,全ての引き出しを名前だけで開けることができないのです.

2012-06-12 23:10:45
JA1TYE/Ryota Suzuki @JA1TYE

これは関数における引数でも同様で,いくら引数に指定したところで,他の関数の中で宣言された変数の中身をいじくりまわすことは許されないのです.だから,データを受け渡したい時には,引き出しの中身をコピーして,相手側の引き出しにそのコピーをしまう,という操作を普通はしています.

2012-06-12 23:13:29
JA1TYE/Ryota Suzuki @JA1TYE

これで割と事足りる,と思いがちですが,問題は他の関数に対して「この引き出しに計算結果をしまってね!」という依頼をするときです.変数名というローカルルールは通用しないので,みんなが理解できる通し番号,すなわちアドレスで引き出しの場所を教えあう必要があります.

2012-06-12 23:15:05
JA1TYE/Ryota Suzuki @JA1TYE

そして,依頼された側の関数では,教えてもらったアドレスを,先ほどの特別な引き出しにしまって,*をつけてもう一度引き出しを開きます.すると依頼元が指定した引き出しの中身を自由にいじることができるようになるので,計算結果をしまう,といったことが可能になります.

2012-06-12 23:17:42
JA1TYE/Ryota Suzuki @JA1TYE

どんな時に使うか,というのはこんなところでしょうか.さて,特別な引き出しは何個も用意できます.各々の特別な引き出しに,同じアドレスを入れて,*をつけて開いてあげたとき,それらの特別な引き出し全てから,1つの実体が見えるということに注意が必要かもしれません.

2012-06-12 23:21:02
残りを読む(3)

コメント

後藤寿庵 @juangotoh 2012年6月13日
まず「アドレス」がわからないという段階の人にポインタ説明するのは難しいよねえ。
0
B.cos式袖車 @bcosizm 2012年6月14日
僕は独学だけど、意外とさらりと理解できた。「そういうルールなのだ!」と割り切ってしまえばとりあえず使える、そのうちわかる。
0