- 変数 -
前のページ 次のページ
リスト
変数って?
変数には種類がある
型について
オーバーフロー
変数って?

プログラムは実行すると 。CPU を中心に動き始めます。CPU はレジスタと呼ぶ記憶領域しか持っていないため、プログラム本体等のデータを保存することができません。では、プログラムはどこに保存するのでしょうか。

実はパソコンにはメモリと言うものが付いていて、そこに保存されるわけです。CPUはその領域から必要な時にごく少量のデータをCPU唯一の記憶領域であるレジスタに読み込み処理を行うわけです。

メモリはデータを記憶するための小さな入れ物が密集しているところです。マンションにたとえると、部屋のようなものです。マンションの場合、部屋には何号室と言うように番号でどの部屋なのかを表すことができますね。それと同じようにメモリは、号番号の変わりにアドレスと言うものでメモリの位置を表すことができます。

C言語ではメモリに値を格納するには、アドレスを指定する時に、変数と言うものを指定します。 C言語では変数は使う前に必ず宣言をしなくてはならないと言う約束があります。そして、C言語で変数を宣言すると言うことは、メモリの特定の領域をこれから使うとコンピュータに知らせていることなのです。だから、C言語を変数を宣言することで、変数を介してメモリにアクセスできるようになるのです。イメージとしては、下図のようになります。

この図のように、C言語は変数を宣言すると自動的にメモリに領域を確保します。上図ではiを宣言しています。そして、宣言したと同時にメモリ上にi用の領域が取得されます。

次にiにデータを代入してみます。上図の矢印の右側のように変数にデータを代入したらメモリに5が代入されることになります。また、メモリの中のデータは、実は何回も書き換えが可能なのです。下のソースコードを見て下さい。

上のソースコードではiを宣言しています。宣言した変数に、まずは5を代入し、printfで出力しています。それ以降は5,10,999と順に代入し出力しています。実行結果を見ると、順々に代入した変数の内容が出力されています。このように変数は繰り返しデータを代入することができるのです。

変数には種類がある

C言語の変数には複数の種類があります。基本的には整数値、実数値を表現する2種類に分けることができます。これらの2つの違いはデータに対するメモリの使い方の違いからなるものです。ためしに、long floatの2つの型を使用して実験してみましょう。この2つはメモリの使用領域は4バイトで、ぞれぞれ、整数値、実数値を代入することができます。それでは、下のソースを見てみてみましょう。

15,16行目で宣言した変数に対して、18,19行目で代入しています。それぞれ100を代入していますが、実際メモリの中身はどう使われているのでしょうか。この実行結果を見るとそれぞれの変数に同じデータを代入したにも関わらず、ダンプを見てみるとaの方は64 00 00 00と言う内容なのに、bの方は00 00 C8 42になっています。このようにC言語は、整数値、実数値でメモリの使い方違うことがわかりましたね。
型について

さっきまでは、メモリの使い方で整数値を扱うもの、実数値を扱うもので分けていました。今度はメモリが使用する領域のサイズで細かく分けていこうと思います。まず、整数値を扱う変数にはchar short int longの4種類があります。それに対して、実数値を扱う変数にはfloat dooubleの2種類があります。そして、その種類のことを型を言います。

Cここで1つ疑問です。なぜ、整数値を表す型には4つ、実数値を表すには2つもあるのでしょうか。
これらの型の違いは表す数値の種類の他にも、メモリを消費するサイズに違いがあるのです。 メモリサイズは、char short int longはそれぞれ1バイト、2バイト、2~4バイト、4バイトとなっています。さらにfloat doubleはそれぞれ4バイト、8バイトとなっています。さて、ここで新しい疑問です。サイズが違うということは、そもそもどういうことなのでしょうか。

これらは扱いたいデータの大きさに関係があります。charのような1バイトの領域しか持たない変数は0~255、または-128~127の範囲までしか表現することができません。
なんでかと言うと、1バイトとは0,1を表現できるビットと言うものが8つあるからです。1ビットと言えば、0 1の2つの状態を表現することができます。 これが2ビットになれば、00 01 10 11の4つの状態になります。3ビットになれば、000 001 010 011 100 101 110 111の8つの状態、これが1バイトにもなれば、256個の状態を表現することができるのです。だから、charは先ほど話した範囲のデータを表現できるのです。ちなみに256と言うのは2の8(ビット)乗のことです。

今、説明した型がshortの場合、2の16(ビット)乗で表すことができる範囲となるわけです。longは2の32(ビット)乗で表すことができる範囲になります。ただ、intの場合はレジストリのサイズに依存するため、2の16(ビット)乗または、2の32(ビット)乗になります。 わかり易いように下に表をまとめてみました。

項番 bit数 範囲 備考
1 char 8 -128~127又は0~255
2 short 16 -32768~32767
3 int 16又は32 16bit:-32768~32767
32bit:-2147483648~2147483647
4 long 32又は64 32bit:-2147483648~2147483647
64bit:-9223372036854775808
~9223372036854775807
5 float 4 -3.4*1038~3.4*1038
6 double 8 -1.7*308~1.7*10308
オーバーフロー
まずは、ここまでの復習もかねて、型とメモリの関係に注目して動きを確認してみよう。

まずdumpbin関数とmain関数を作りました。dumpbin関数はメモリの状態を2進数文字列で出力する関数になります。処理の動きは main関数のコードを追って見ましょう。
29行目のunsignedと言うキーワードを説明しようと思います。これが付くとその変数はマイナス無しの数値を保持することになります。charの場合、元々使用できる数値の範囲は-128~127までだったので、マイナスを使用しないとなると使用できるデータ範囲が0~255までに変更します。
35~39行目は29行目で宣言した変数に1加算しながら、メモリ内容を表示しています。繰り返し回数が256回なので、256回目のループでは0~255と範囲を超えて255に1を加算使用します。そのような時、cの中のデータはどのような動きをするのでしょうか。

実行してみると、上記のような結果になります。 一番左の数値がその時のcの値です。真ん中がアドレス(無視しましょう)です。一番右が数値を2進数で表現したもの(参考にしてね)になります。結果を見るとc0から始まり255まで出力していますね。255まで出力した後、0に戻っています。これが答えになります。C言語では宣言した変数の有効範囲を超えた場合、元の状態に戻ってしまいます。時計の針が繰り返し回っているかのように、同じデータ範囲をぐるぐる回っているのです。そして、この元に戻る現象のことをオーバーフローと言います。



前のページ 次のページ