C言語入門|変数アドレスを取得する

変数が「どこにあるか」を知る

ここからはいよいよ、
C言語が持つ低水準な顔 に足を踏み入れていきます。

前の節で、変数の正体は
「メモリのどこかに確保された領域」
だと分かりましたね。

でも、こんな疑問が浮かびませんでしたか?

その「どこか」って、具体的にどこ?

多くの高級言語では、この疑問を持つことすらできません。
ところが C言語では―
調べようと思えば、変数の場所そのものを調べられる
のです。

メモリ番地を表で表してみよう

まずは、メモリをもう一度イメージで確認しましょう。

メモリは巨大なマス目の集合で、
それぞれに 番地(アドレス) が振られています。

例として、次のように表で表すことができます。

番地\列01234567
1000
1008
1016
1024

このように、

  • 行が「大まかな番地」
  • 列が「1バイトずつの位置」

を表していると考えると分かりやすいです。

変数アドレスとは何か

変数を宣言すると、C言語とOSが協力して
連続したメモリ領域 を確保します。

たとえば、

int score;

と宣言した場合、int型が4バイトなら、

  • ある番地を先頭として
  • 4バイト分の領域

が使われます。

このとき重要なのが、

その変数の先頭の番地

これを
変数のアドレス
と呼びます。

アドレスを取得する方法

C言語では、次の構文を使うことで
変数のアドレスを取得できます。

アドレス取得の書式

書式意味
&変数その変数が確保されているメモリ領域の先頭番地

この & は、
アドレス演算子
と呼ばれる演算子です。

値を取り出すのではなく、
「場所そのもの」に化ける

と考えると理解しやすいですよ。

サンプルプログラムで確認してみよう

では、実際に変数のアドレスを取得してみましょう。

プロジェクト名:9-5-1 ソースファイル名: sample9-5-1.c

#include <stdio.h>

int main(void)
{
    int points = 85;

    printf("得点は %d 点です。\n", points);

    long address = (unsigned long)&points;
    printf("points の先頭アドレスは %ld です。\n", address);

    return 0;
}

実行結果の一例

※ここでは、実行結果をこの後の説明のため「4016」にしています。実際に表示される数値は、非常に大きな数値が表示されます。

得点は 85 点です。
points の先頭アドレスは 4016 です。

※ 実行するたびに、アドレスの値は変わります。

使用している命令と役割

このプログラムで使われている命令を整理してみましょう。

命令書式役割
intint 変数名整数型の変数を宣言する
&&変数変数の先頭アドレスを取得する
(long)(型)値型キャストを行う
printfprintf(書式, 値)情報を画面に表示する
returnreturn 値main関数を終了する

ここでポイントになるのが 型キャスト です。

アドレスは環境によって非常に大きな値になるため、
今回は安全のため unsigned long 型に変換してから表示しています。

アドレスは「1点」ではない

表示されたアドレスを見て、
「この番地だけが使われている」
と思ってしまいがちですが、それは誤解です。

たとえば、次の状況を考えてみましょう。

int points = 85;
  • points の型は int
  • int のサイズは一般的に 4バイト

この場合、確保されるメモリ領域は次のようになります。

番地内容
4016points の一部
4017points の一部
4018points の一部
4019points の一部

つまり、

&points で取得できるのは
4016 番地(先頭)だけ

という点が非常に重要です。

& 演算子の本当の意味

ここで、& 演算子の役割をまとめておきましょう。

観点内容
取得できるもの変数の先頭アドレス
取得できないものサイズ全体や中身
型との関係型のサイズ分の領域が背後に存在

& 演算子は、
メモリ操作の入口
とも言える存在です。

まとめ:なぜアドレスを知る必要があるのか

「場所なんて知らなくても、
変数が使えればいいじゃない」

そう思うのは自然です。
実際、高水準な世界ではそれで問題ありません。

しかし、C言語では次のような場面で
アドレスの知識が不可欠になります。

  • 関数に値そのものではなく「場所」を渡したいとき
  • 配列や構造体を効率よく扱いたいとき
  • メモリを直接操作する必要があるとき

そのための第一歩が、
変数のアドレスを取得すること
なのです。

次の一歩へ

次は、
この「アドレス」を変数として扱う―
ポインタ
の世界に進みます。

ここからが、C言語の本番です。

ここまで理解できたあなたは、
もう C言語の低水準世界の入り口 に立っています。
次は一緒に、ポインタを攻略していきましょう。