ポインタ

ポインタとは、一部の高水準言語において、ソースコード上でメモリアドレスの格納ができ、指定したデータ型でそのメモリアドレスにアクセスできる特殊な変数*のことです。

ポインタの宣言

ポインタの宣言とは、「ポインタの名前」と「ポインタに格納したメモリアドレスにアクセスする際に利用するデータ型」を指定して、そのポインタをソースコード上で使えるようにすることです。

例えば、あるプログラミング言語では、intという整数型でポインタpを宣言するには、以下のようにします。

int *p;

なお、このプログラミング言語では、以下のように*の前後のスペースの有無は問いません。

int* p;

int * p;

int*p;

ポインタへのメモリアドレスの代入

例えば、上記のポインタpにメモリアドレス2000を代入するには、以下のようにします。

p = 2000;

このように、ポインタに任意のメモリアドレスを代入するのは、プログラミングする側がメモリアドレスを管理できる場合です。

なお、宣言したポインタに初めて行うメモリアドレスの代入のことをポインタの初期化と言います。

同じプログラミング言語でポインタの宣言と初期化を同時に行うには、以下のようにします。

int *p = 2000;

ポインタ演算

ポインタを用いた計算は、「ポインタと整数の足し算」と「ポインタと整数の引き算」のみ可能です。これらの計算をポインタ演算と言います。ただし、ポインタ演算は、以下の特殊な挙動をします。

・ポインタpのデータ型のバイト数をB、適当な整数をnとした場合、ソースコード上でp + nとすると、参照されるメモリアドレスは、p + B × nになる。

つまり、p + nにより、pを基準としたn番目のBバイトのデータのメモリアドレスを参照することができます。

例えば、以下のように、ポインタpに1を加算したとします。

int *p = 2000;
p = p + 1;

すると、ポインタpの値は、2004になります。ポインタに1を加算して、メモリアドレスが4増えたのは、ポインタのデータ型のバイト数が4バイトであるためです。

なお、以下のようにポインタに加算する値を整数型の変数*にすることもできます。

int *p = 2000;
int n = 2;
p = p + n;

ポインタが指し示す値の参照

ポインタに格納したメモリアドレスから宣言時に指定したデータ型でデータを読み出して利用することをポインタが指し示す値の参照と言います。

例えば、あるプログラミング言語では、ポインタpが指し示す値を*pで参照できます。以下は、そのプログラミング言語で変数*a*pの値を代入して、*pを参照する例です。

int *p = 2000;
a = *p;

この場合、intが4バイトの整数型であれば、*pでメモリアドレス2000から4バイト分のデータが読み出され、intの値として、変数*aに代入されます。

また、ポインタ演算を利用して、以下のように一時的にポインタが指し示す値をずらすことができます。

int *p = 2000;
a = *(p + 1);

この場合は、*(p + 1)でメモリアドレス2004から4バイト分のデータが読み出され、intの値として、変数*aに代入されます。このとき、pの値は、2000のままです。

ポインタが指し示す値の書き換え

ポインタが指し示す値は、以下のように書き換えることができます。

int *p = 2000;
*p = 3;

この場合、メモリアドレス2000intの3が書き込まれます。つまり、intが4バイトの整数型であれば、メモリアドレス2000から4バイト分のメインメモリが書き換えられます。

また、ポインタ演算を利用して、以下のように一時的にポインタが指し示す値をずらして、その値を書き換えることができます。

int *p = 2000;
*(p + 1) = 10;

この場合、メモリアドレス2004intの10が書き込まれます。

ポインタの仕組み(ハードウェアレベル)

ポインタは、ハードウェアレベルでは、以下の仕組みで実現されています。

・ポインタの実体は、あるメモリアドレスに割り当てられたメインメモリです。ポインタの宣言を行うことでそのメインメモリが確保されます。

・ポインタには、メモリアドレスを格納するため、ポインタ用に確保されるメインメモリのバイト数は、アドレスバスのバス幅(1ワード)と同じです。

・ポインタへの値の代入は、ストア命令でポインタのメモリアドレスに代入したい値をコピーすることで実現します。

・ポインタ演算は、「符号なし乗算命令もしくは符号あり乗算命令」と「加算命令」を利用して、参照するメモリアドレスを計算します。

・ポインタが指し示す値の参照は、ロード命令でポインタの値Aを読み出し、さらにロード命令でA(メモリアドレス)に保存されている値を読み出すことで実現します。

・ポインタが指し示す値の書き換えは、ロード命令でポインタの値Aを読み出し、ストア命令でA(メモリアドレス)に書き換えたい値をコピーすることで実現します。