ログイン
kid's world

変数とメモリの関係

変数とメモリの関係

これでひととおりの説明は終わった。なんとなく変数のイメージがつかめたと思う。しかし,ここまで解説してきたのはC言語の表面上の話にすぎない。そこでもう少し突っ込んだ話をしてみよう。

メモリとは0と1を覚えるだけのIC

以前,コンピュータを構成する重要な要素の1つとして「メモリ」を取り上げた。メモリは大量のデータやプログラムを記憶するIC(集積回路)である。さぞかし複雑な構造をしていて,中では高度な処理がされていると思われるかもしれない。しかし,メモリの基本的なアイデアは単純である。

メモリは,

0と1の羅列をたくさん覚えられるもの

でしかない。0か1かを区別できる最小単位をビット(bit)と呼び,通常のコンピュータは8ビットを1つのかたまりとして処理している(Fig. 5)。

Fig. 5: ビットとバイト

/c/var-fig5.png

よく「256MBのメモリを搭載している」などという言葉を聞くであろう。「MB」は「メガバイト」と読み,1MBはほぼ100万バイトである。つまり,256MBのメモリには約20億の0と1の羅列を記憶できるわけである。複雑さより量で勝負,というわけだ。

データはすべて0と1に

変数には3.14159など複雑な数値を記憶できる。そして変数はその数値をメモリ上に記憶している。しかし,メモリは0と1しか覚えられない。まさか,気合と根性で覚え込ませているわけではない。いくらなんでも気合と根性はメモリには通じない。

ここで,あなたの右手を見ていただきたい。この「右手だけで」,0から31までの数字を数えてみよう。右手は5までしか数えられないというのは固定概念である。では,それぞれの指の腹に,Table 3のように数字を書いてほしい。

Table 3: 右手の指に対応する数字

/c/var-table3.png

準備はできただろうか。それでは,すべての指を折り曲げ「グー」の形にしよう。指の数字は見えない。したがって,この状態は「0」だ。では次に,自分に向かってピースをしてみよう。人差指と中指の数字が見えたと思う。これらの数字を足すと6になる。よって,この状態は「6」だ。では,次にすべての指を開いて「パー」の状態にしてみよう。見えたすべての数字を足すと31になる。

実は,このようなやり方で,片手で0から31までの好きな数値を表現できるのだ。さらに左手も使うとすごいことになる。右手の場合と同様,左手にはTable 4に示す数字を書いてほしい。このようにすると,両手を使ってなんと0から1023までの数値を表現できるようになる。

Table 4: 左手の指に対応する数字

/c/var-table4.png

「指で数えるほどしかない」という言葉があるが,1023まで数えられるのだから,そのような言葉はめったに使うべきではない(笑)。

さて,指を折り曲げた状態を「0」,指を立てた状態を「1」としよう。するとどうだろう,10個の0と1の羅列で0から1023までの数値を表現できたことになる。そう,実はメモリにはこのような形で数値が記録されているのだ。たとえば100なら「1100100」,200なら「11001000」という具合である。このような表記方法を「2進法」と呼び,その数値自身を「2進数」と呼んでいる。ちなみに私たちがふだん使っているのは「10進数」である。

しかし,これでは正の整数値しか表現できない。実際には負の整数値を表現するために「2の補数表現」,実数値を表すために「浮動小数点表現」などを用いる。これらについて詳しく説明すると話が難しくなるので,もし興味のある方は,各自で勉強していただきたい。ともかく,どのようなデータもすべて0と1の羅列に変換することができるのだ,ということを知っておいていただきたい。

型のサイズ

通常のコンピュータでは,メモリは8ビット単位で1つのかたまりになっているということは,すでに述べたところである。すなわち,8ビット=1バイトで256種類の値を表現できるわけである。しかし,これでは一般的に用いられる数値としては表現の幅が狭すぎる。そこで通常は,数値を表現するときは,2バイト以上のメモリを使う。そのサイズは型によって異なる。ただし,int型なら必ず4バイト使うというわけでもなく,それはコンパイラ(処理系)によって異なるため,注意が必要だ。本誌に収録されているLSI C-86 Ver.3.30 試食版の場合は,Table 5のようになる。

Table 5: 型とサイズ(LSI C-86 Ver.3.30試食版の場合)

/c/var-table5.png

どの型がどれだけのバイト数を使用するのかは,sizeof演算子によって知ることができる。たとえばint型の使用するバイト数を知りたい場合は,

sizeof(int)

とする。すると「sizeof(int)」全体が,int型が使用するバイト数を整数値で表すようになるので,

int size;
size = sizeof(int);

と書けば,size変数にint型のサイズが代入されるし,

printf("%d\n",sizeof(int));

と書けばそのサイズが表示される。参考までに,それぞれの型のサイズを表示するプログラムをList 6に書いておこう。

List 6:それぞれの型のサイズを表示

#include <stdio.h>

main()
{
  printf("int: %d\n",sizeof(int));
  printf("short: %d\n",sizeof(short));
  printf("long: %d\n",sizeof(long));
  printf("float: %d\n",sizeof(float));
  printf("double: %d\n",sizeof(double));
  printf("long double: %d\n",sizeof(long double));
}

表現できる値の範囲

LSI C-86では,int型を表すのに2バイトのメモリを使っている。ということは,2バイトで表現できない数値は扱えないということである。

では,その限界を体験してみよう。List 7を見ていただきたい。最初にint型変数iに32767を代入してその内容を表示し,次に変数iの内容を1増加してその内容を表示している。

List 7: int型の限界

#include <stdio.h>

main()
{
  int i;
  i=32767;
  printf("%d\n",i);
  i++;
  printf("%d\n",i);
}

本当ならば,2行目で32768と表示してほしいところだが,実行結果は,

32767
-32768

となる。どういうことだろうか。1足しただけなのに,負の値になってしまった。実は,これがLSI C-86におけるint型の限界を超えた瞬間なのだ。

このとき,内部では何が起こっているかを2進数(2の補数表現)による計算によって見てみよう。32767は0111111111111111,-32768は1000000000000000と表現されている。つまり,

/c/var-fig6.png

という計算になる。なるほどこれは2進数で考えれば当たり前の話である。しかし,それが10進数になったときに,あのような信じられない結果となるのだ。

このように,C言語上には表現できる値にある決まった範囲がある。そして,それを超える結果となる演算を行っても,エラーも何も出ないということを知っておいていただきたい。参考までに,LSI C-86の場合の表現可能な値の範囲をTable 6にあげておく。現在一般的に使われているコンパイラでは,これよりももっと広い範囲の値が表現できるものが多い。

Table 6:表現可能な値の範囲(LSI C-86の場合)

/c/var-table6.png

生まれたての変数

変数は宣言されるときに,メモリのどこかを「確保」する。「ここは俺が使う!」と宣言するわけだ。

しかし,その確保したメモリは,以前に誰が使っていたかわからない。メモリを使い終わったときに,すべて「0」にして解放しなければならないという決まりがあるわけではないので,メモリを確保したとき,まったく予想できない値が書き込まれていることになる。

これを,List 8のプログラムで確かめてみたい。コンパイラによっては,警告が出る場合があるかもしれないが,文法上は間違っていないので,コンパイルは成功するはずだ。

List 8: 生まれたての変数

#include <stdio.h>

main()
{
  int i;
  printf("%d\n",i);
}

それでは,このプログラムを実行してみよう。画面上にはどんな数値が表示されただろうか? 運よく「0」が表示された人は少ないだろう。ほとんどの場合,でたらめな数値が表示されるはずだ。

このプログラムから学ぶことができるのは「変数は必ず初期化をしてから使わなければならない」ということだ。生まれたての変数の値は必ず「0」だと決めつけてしまうと,痛い目にあうことがあるのだ。

おわりに

さて,今回はこれでおしまいだ。変数とメモリの関係はなんとなくわかっただろうか。次回は,今回の話に続いて,さらに変数とメモリの関係に密接なC言語の機能について解説をする。少々難しい話であり,C言語の中でいちばんの山場といってもいいかもしれない。だが,わかれば楽しいところでもある。ぜひ期待して待っていていただきたい。


変数の居場所」へ進む

広告


©Toshio Koide 1996-2007.

目次

リンクについて

リンクは御自由にどうぞ。

メール

mail.gif

広告