メモリアドレス

変数のデータが保存されているメモリアドレスを取得するには、単項&演算子を用います。この演算子は、右オペランドに指定された変数のアドレスを返します。このアドレスのことをポインタと呼びます。通常、システムの内部では整数でアドレスが表現されていますが、C言語にとって物理的なメモリアドレスの形式は重要ではありません。

& 変数名

この演算子が返す結果は、変数のポインタとなります。ポインタの宣言については後述するとして、この場では演算子が返した結果となるメモリアドレスを画面に表示してみましょう。異なる変数であれば、異なるメモリアドレスが得られることを確認できます。アドレスの形式はシステムに依存するため、printf()関数の書式で%pを使います。一般的なシステムではアドレスは整数型と互換性がありますが、それを前提としたコードはシステムに依存してしまいます。

Sample01

#include <stdio.h>

int main(void)
{
    int x, y;

    printf("&x=%p\n&y=%p\n", &x, &y);

    return 0;
}

実行結果

サンプル01の実行結果

Sample01 は、整数型の変数 x と y のアドレスを取得してprintf()関数で表示しています。得られる結果は環境やシステムに依存しますが、Visual C++で開発したプログラムであれば、上記のような16進数でアドレスが表示されます。整数そのものに意味はありません。この値が、変数に保存しているデータのある場所を表しているということが重要です。

変数のアドレスとして取得した値から、間接演算子と呼ばれる単項 * 演算子を用いて変数のデータにアクセスできます。この演算子のオペランドには、常に有効なポインタでなければなりません。* 演算子はオペランドに指定されたポインタから、元の変数を参照して結果を返します。

* ポインタ

つまり、ポインタが指す変数そのものが結果として得られます。変数 x が存在するときに、変数 x のポインタは &x で取得することができ、このポインタから変数 x の値を間接的に参照するには *(&x) となります。よって、以下の関係演算の条件は常に満たされます。

*(&x) == x

なぜこのようなことをする必要があるのかというのは後述します。この場では、間接演算子 * を使うことによって、ポインタが指すアドレスを辿って変数 x の値を取得できるということを理解してください。