コンピュータで扱うデータには「型」がある。我々人間も,扱うデータが数値なのか文字なのか,はたまた映像なのかくらいは意識するけれど,コンピュータでいう型はそれよりもっとややこしそうだ。

 「型」について調べていくうちに,人間の脳ミソで展開される情報とコンピュータのメモリーの中で扱われる「データ」との決定的な違いがわかってきた。

 調査結果は非常に膨大なものとなったため,今回は「符号付き/符号なし」と「桁あふれ」の問題を中心に報告する。

変数にも,定数にも,処理にも,型がある

 プログラミングに「型」は付きものだ。一般には「データ型」と言われる。コンピュータで扱うデータには必ず値と型がある。データ型というと変数だけが対象となるような気がするけれど,そうでないことは読者ならご存じのはず。定数*1にも型がある。

 Cでは,型を明示しない整数の定数はint型とされる。int型以外のデータと演算する場合には,キャストの必要がある。

float x, y;
 …
x = (float)1000 * y; /* 定数'1000'をfloat型にキャスト */

 定数の型を明示する場合には,後ろに型を示す記号を付加する*2。例えばlong型なら“L”を使う(小文字でも可)。

/* long型の整数'1000'を記号定数'__MAX'として定義 */
#define __MAX 1000L;

 Visual Basic(VB)ではConst命令を使って*3次のように定数を宣言する。

Const __MAX = 1000

 このVBの例でも型は暗黙のうちに決まる(上の例ならInteger)。が,宣言セクションで“Option Strict On”として明示的な型変換を強制するよう設定すれば,以下のようにAs句を使って定数の型を明示しなければならなくなる。

Const __MAX As Integer = 1000

 データだけではなく,コード(処理)にも型がある。関数やプロシジャの型だ。VBでは値を返すFunctionプロシジャが型を持ち,値を返さないSubプロシジャは型を持たない。それぞれの宣言は,以下のように異なっている。

Function GetMaxNum () As Integer ――値を返す
Sub ViewFileName()           ――値を返さない

 Cの場合は,基本的にすべての関数が型を持つ。関数の宣言では,必ず戻り値の型を示さなければならない。何の値も返さない関数も,voidという「型がないことを示す型」をあてる。

int getmaxnum();   ――値を返す
void viewfilename(); ――値を返さない

 プロシジャや関数の型というのは,それらが返す値の型である。だから,やはり「値=データの型」なのだ。

誰がどこで型を決めているのか?

 さて,データの型とは何なのだろう? この疑問を突き詰めていくと,コンピュータと人間との違いが見えてくる。

 「データ型って何?」と問われれば,「そんなの決まってるよ。整数とか小数とか文字列とか…」と,声が聞こえてきそうだ。もちろんそれはわかっているのだが,では,「あるデータが整数(例えばVBのInteger)である」というのは,一体どういう状況なのだろう?

 マイクロソフトのオンライン・ドキュメントには,VBのInteger型について以下のように記されている。

整数型(Integer)の変数は,32ビット(4バイト)の符号付き整数として格納され,-2,147,483,648~2,147,483,647の範囲の値をとります。

 まぁ,そうゆうことだ…と,ここで納得してはいけない。確かに書いてある通りなのだが,上のようなことはどこでどのように規定されているのだろうか? もちろん処理系(この場合ならVB)が規定しているわけだが,どんな仕組みで,例えば「Num As Integer」という宣言を「Numという名前の変数には-2,147,483,648 ~ 2,147,483,647の範囲の符号付き整数を格納する」という処理に対応させているのだろう?