補足: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 と同じ */