補足: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 が表示される */
exit(1);
}
◇「手続きへ」・上へ
○ポインタと配列
・単純変数と同じように、配列要素 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 と同じ */
「手続きへ」