みえるCお試し版

トラック 10・メモリの仕組み

メモリとは巨大なロッカー群

読む目安 約10分 ねらい: メモリを「1バイトごとに番地が振られたロッカーの列」としてイメージでき、変数と型の役目を番地の言葉で説明できる

このレッスンの要点

  • メモリは1バイトごとに区切られ、0番から連続した番地が振られている
  • 変数はロッカーの予約であり、名前は機械語では番地に置きかわっている
  • 型はロッカーを何個使うか(大きさ)と、中身をどう読むかを決める
  • ポインタの前に番地に慣れる——それがトラック10の目的

駅のコインロッカーを思い浮かべてください。壁一面に扉が並び、どの扉にも「1番」「2番」「3番」と番号が振ってあります。荷物を預けたあとに覚えておくのは、中身ではなく番号だけ。番号さえ分かれば、いつでも取り出せます。

コンピュータのメモリも、まったく同じ作りをしています。第2部「メモリの洞窟」では、このロッカー群の中を歩いて回ります。

番地が振られたロッカーが一列に並ぶ、メモリのイメージ図
番地が振られたロッカーが一列に並ぶ、メモリのイメージ図
ポインタ姫ようこそ、メモリの洞窟へ。わたくしはこの国の郵便屋、ポインタ姫と申しますわ。番地さえ分かれば、どこへでも届けられますの

メモリは1バイトごとに番号が振られている

メモリは「1バイト(8ビット)」ごとに区切られ、その1区画ずつに通し番号が付いています。この番号をアドレス(番地)と呼びます。番地は0番から始まり、1つずつ増えながら、途切れることなく最後まで続きます。

大切な性質が2つあります。同じ番地は1つしかないこと、そして番地は必ず連続していることです。この2つのおかげで、コンピュータは「3000番地の中身をください」と言うだけで、探し回ることなく一発で目的のデータへたどり着けます。メモリが速いのは、この番地のしくみのおかげです。

番地は数値です。人間が見るときは16進数で 0x7ffd5a20 のように書きますが、中身はただの通し番号にすぎません。何億個ものロッカーが一列に並んでいる、と考えてください。8GBのメモリなら、ロッカーはおよそ86億個あります。

変数は、予約済みのロッカー

ここまで使ってきた変数の正体も、このロッカーの予約でした。

int score = 80;

この1行でコンピュータは「int1個分の広さのロッカーを空けておき、そこに80を入れる。以後その場所を score と呼ぶ」という手配をします。

ビットえっ。じゃあ score って名前は、機械にとっては本物じゃないの?

そのとおりです。名前はコンパイルの時点で番地に置きかえられ、出来上がった機械語のなかに score という文字はもう残っていません。名前は人間のための道具で、実行中の機械が見ているのは番地だけなのです。

型はロッカーの大きさと読み方を決める

型には2つの役目があります。1つはロッカーを何個使うか、もう1つは中身をどう読むかです。ふつうの環境では、char が1バイト、int が4バイト、double が8バイトを使います。

つまり int score; は、4つのロッカーをまとめて1つの箱として予約している、ということです。占領する番地も4つぶんなので、次の変数はその先に置かれます。sizeof 演算子を使えば、その型がロッカーを何個使うか自分で確かめられます。printf("%zu\n", sizeof(int)); と書けば、たいていの環境で 4 と表示されます。

読み方の指定も型の仕事です。ロッカーの中に入っているのは0と1の並びだけなので、型がなければデータはただのビットの列です。同じ4バイトでも、int として読むか float として読むかで、意味はまったく変わってしまいます。

なぜ番地の話から始めるのか

多くの人がつまずくポインタは、突きつめれば「番地を入れておく変数」でしかありません。ところが番地そのものに慣れないままポインタへ進むと、分からないものが2つ同時に来て混乱します。そこでこの教材では、トラック10をまるごと番地の話に使います。急がば回れです。

まとめ

メモリは1バイトごとに番地が振られたロッカー群です。変数はそのロッカーの予約で、型が大きさと読み方を決めます。ここで番地に慣れておけば、次のトラックのポインタは「番地を書いたメモ」として素直に受け取れます。

アプリでこのレッスンを動かして学ぶ(無料・登録なし)

動かして確かめるコード

#include <stdio.h>

int main(void) {
    int score = 80;
    int bonus = 5;
    score = score + bonus;
    printf("%d\n", score);
    return 0;
}

確認問題

確認問題 1

メモリの説明として、もっとも正確なものはどれでしょう。

  1. 1バイトごとに区切られ、それぞれに0から連続した番地が振られた記憶装置
  2. 変数の名前をそのまま覚えていて、名前で中身を出し入れする記憶装置
  3. 番地はプログラマが自由に決められ、好きな場所に変数を置ける記憶装置
  4. 1文字ごとに区切られ、電源を切っても中身が残る記憶装置
答えを見る

正解: A(1バイトごとに区切られ、それぞれに0から連続した番地が振られた記憶装置)

メモリは1バイト単位で区切られ、0から連続した番地(アドレス)が振られています。変数名は人間のための呼び名で、コンパイル後の機械語には残っていません。番地を決めるのはコンパイラとOSの仕事で、プログラマは指定しません。また電源を切れば中身は消えます(保存にはファイルが必要です)。

確認問題 2

int score = 80; と書いたとき、メモリで起きることの説明として正しいものはどれでしょう。(int は4バイトとします)

  1. 4バイトぶんの連続したロッカーが確保され、そこに80が入る。score はその場所の呼び名
  2. 80 が入っているロッカーが探され、そこに score という名札が貼られる
  3. 1バイトのロッカーが確保され、そこに80が入る
  4. score という名前のロッカーが作られ、実行中も名前で検索できるようになる
答えを見る

正解: A(4バイトぶんの連続したロッカーが確保され、そこに80が入る。score はその場所の呼び名)

int は4バイトなので、連続する4個のロッカーが1つの箱として予約されます。名前 score はコンパイル時に番地へ置きかえられるため、実行中のメモリに「名前で探す」しくみは存在しません。

「メモリの仕組み」の目次

  1. メモリとは巨大なロッカー群
  2. アドレス——すべての箱に番地がある
  3. プログラムのメモリレイアウト有料版
  4. スタックフレームを覗く有料版
  5. 変数の番地を見る——&演算子有料版
  6. バイトとエンディアン有料版
  7. メモリの図の使い方有料版

この先へ ポインタ・メモリ・構造体・ファイル入出力まで、全26トラック・211レッスン・演習508問は有料版に入っている。

有料版(BOOTH)を見る

ほかのトラック

姉妹品: 手を動かして覚える Linux 教材 Linux とインフラの仕組みを地図で学ぶ

Web 版 / BOOTH