補足:C 言語のポインタの概念
◎型とアドレス(型と変数についての補足)
・コンピュータの中で、変数にデータを「格納」することは
”型”で決められた形式でメモリ(記憶装置)のある”場所”に
「格納」することである。
・”場所”は「アドレス」という数値で表現される。
Cプログラム中で変数のアドレスは、「& 変数名」と書く。
・”型”は、「処理の仕方」の手順として、機械語プログラムに
埋め込まれる。
・「変数」のアドレスは、コンパイラが自動的に決定するので、
プログラマが設定することはできない。
変数のアドレスは、変えることができないので、
「&変数名 = 100 ;」のようなことはできない。
◎ポインタ変数(または単にポインタ)
・「ポインタ変数」は他の変数を「指し示す」変数
「ポインタ変数」の「変数」は、「何を指し示すか」が
変化するという意味である。
!! 「指し示す対象となる変数」と「ポインタ変数そのもの」を
混同しないように注意する
・ C言語ではあるポインタ変数は特定の型の変数だけを指す。
・「ポインタ変数」の実体は、アドレスという数値を格納する変数
である。
○ポインタ変数の使い方
・ ポインタ変数 p をつかって指示対象変数を参照するときは
*p と書く。
(乗算の記号と同じだが、* の左に何もないので区別される)
・「ポインタ変数」の宣言は、
「指し示す対象の型 *ポインタ変数名 ;」
の形で行なう。例えば整数変数を差すポインタ変数 p の宣言は、
int *p;
となる。これは、「*p は整数型」と解釈すればよい。
!! 注意: この宣言で確保されるのは、アドレスを格納する場所
だけである
指し示す対象となる整数変数の場所は確保され * ない *
使用する前にかならず、実際の変数のアドレスを代入しておく
仮パラメタの場合、関数呼出のとき自動的に代入される。
(もちろん、正しい実パラメタで呼び出した場合)
・「何も指していない」ことを示すために慣習として記号「NULL」を使う。
これは、 stdio.h で定義されている。
例:
#include <stdio.h>
main()
{
int n1, n2, n3;
int *p;
n1 = 123;
n2 = 456;
p = &n1; /* ポインタ変数 p に、変数 n1 のアドレスを代入 */
n3 = *p; /* p の指す変数の内容を n3 に代入 */
/* 結局 n1 の内容が代入される */
printf("%d\n", n3); /* 123 が表示される */
p = &n2; /* ポインタ変数 p に、変数 n2 のアドレスを代入 */
n3 = *p; /* p の指す変数の内容を n3 に代入 */
/* ここでは n2 の内容が代入される */
printf("%d\n", n3); /* 456 が表示される */
*p = 789;
printf("%d\n", n2); /* 789 が表示される */
}
○ポインタと配列
・単純変数と同じように、配列要素 a[i] のアドレスは、&a[i] と書く。
・特に配列の最初の要素 a[0] のアドレス &a[0] は簡単に a と書いてよい。
この a は配列の「アドレス」であり、値が変更できない点を
除いてはポインタ変数と同じである。
a[0] の代わりに *a と書いてもよい。
・逆に p がポインタ変数のとき、*p の代わりに p[0] と書いてもよい。
・p = a; /* これは p = &a[0] と同じ */
となっている時、p[1] を操作することは、a[1] を操作することになる。
p[i] = p[i]*2; /* あらかじめ p = a となっていれば、
a[i] = a[i] * 2 と同じ */