
C言語入門|アドレスから値を取り出すしくみ
ポインタが「中身」に変わる瞬間
前の節では、
変数のアドレスを & 演算子で取得し、ポインタ型の変数に格納できる
というところまで学びました。
ここで、誰もが次の疑問を持ちます。
アドレスを手に入れたけど、
それで何ができるんですか?
答えはシンプルです。
アドレスを使って、メモリの中身を直接読み取れる。
これこそが、C言語が「低水準」と呼ばれる理由のひとつです。

アドレスから情報を取り出すための演算子
メモリ上の指定番地に書き込まれている値を取り出すには、
次の構文を使います。
間接演算子(デリファレンス演算子)
| 書式 | 意味 |
|---|---|
| *ポインタ変数 | ポインタが指す番地の中身を取り出す。 |
この * 演算子は、
- ポインタ変数に格納されているアドレスを使って
- その番地にある情報を読み取り
- 値として振る舞う(値に化ける)
という働きをします。
まずは全体像を確認するサンプルプログラム
次のプログラムを見てください。
あえてコンパイルエラーが出る例 から始めます。
#include <stdio.h>
int main(void)
{
int score = 85;
printf("スコアは %d 点です。\n", score);
void* addrScore = &score;
printf("score のアドレスは %p です。\n", addrScore);
printf("%p 番地の中身は %d です。\n", addrScore, *addrScore);
return 0;
}プログラムの流れをメモリ視点で追ってみよう
ここからが本番です。
1行ずつ、メモリの中で何が起きているか を見ていきましょう。
① 変数が生まれる
int score = 85;この行で行われていることは次のとおりです。
| 処理 | 内容 |
|---|---|
| メモリ確保 | int 型 4バイト分の領域を確保 |
| 初期化 | その領域に 85 を書き込む |
仮に、score が次の番地に配置されたとします。
メモリのイメージ(例)
| 番地 | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| 4000 | 85 | |||||||
| 4008 | 4000 | |||||||
② アドレスを取得してポインタに入れる
void* addrScore = &score;この1行では、実は次の3つが同時に行われています。
| 手順 | 内容 |
|---|---|
| (1) | score の先頭アドレスを調べる。 |
| (2) | ポインタ変数 addrScore を作る。 |
| (3) | 調べた番地を addrScore に代入する。 |
メモリ状態(イメージ)
| 変数 | 番地 | 中身 |
|---|---|---|
| score | 4000 | 85 |
| addrScore | 4008 | 4000 |
addrScore は
score の値ではなく、score の場所を指している
ことがポイントです。
いよいよ * 演算子の出番
問題の行がこちらです。
*addrScoreこの式の意味を、日本語で正確に書くとこうなります。
addrScore に入っている番地を使って
その番地に格納されている値を取り出す
addrScore の中身は 4000
つまり、
4000 番地の中身を読め
という命令になります。
気づいた人は鋭い
ここで、こう思いませんでしたか?
あれ?
*addrScore って、score と同じじゃない?
その通りです。
| 表現 | 意味 |
|---|---|
| score | 4000 番地に入っている値 |
| *addrScore | 4000 番地に入っている値 |
同じメモリを、別の書き方で表しているだけ なのです。
これが、
*addrScore は score の別名
と言われる理由です。
ではなぜ、このプログラムはエラーになるのか?
ここまでの説明を読むと、
「ちゃんと 85 が表示されそう」
と思うかもしれません。
しかし、実際にはコンパイルエラーになります。
理由は void 型の制限 にあります。
void* 型では中身のサイズがわからない
コンパイラの立場で考えてみましょう。
| コンパイラの疑問 | 内容 |
|---|---|
| どこから? | addrScore が指す先頭番地 |
| どこまで? | 何バイト分読むの? |
void* 型は、
- アドレスであることは分かる。
- しかし その先にあるデータ型が分からない。
という特徴を持っています。
void* 型の限界
| 項目 | 内容 |
|---|---|
| できること | アドレスを保持する |
| できないこと | 中身のサイズを判断する |
| 結果 | * を使うとコンパイルエラー |
つまり、
先頭番地は分かるけど、
何バイト読めばいいのか分からない
これがエラーの正体です。
ここまでの理解が超重要
この節で、必ず押さえておいてほしいポイントを整理します。
| ポイント | 内容 |
|---|---|
| & 演算子 | 変数の先頭アドレスを取得する。 |
| * 演算子 | 指定番地の中身を取り出す。 |
| ポインタ | 「値」ではなく「場所」を扱う。 |
| void* | アドレスは持てるが中身は扱えない。 |
ここまで理解できたなら、
ポインタ学習の第一関門は突破 です。
次に進む前のひとこと
次の記事では、
- void* ではなく
- 「どの型のデータか分かるポインタ」
を使って、
安全に * 演算子を使う方法 を学びます。
そこから、
ポインタは一気に「便利な道具」へと変わります。
ここまで来たあなたは、
「アドレス」と「値」を頭の中で行き来できる段階 に到達しています。
次は、
いよいよ 型付きポインタの世界 です。
