本当に初心者の人に捧げるコンピューター入門


ソフトウェア プログラム編その6

もっとややこしい物に名前をつける

 この章では名前を付ける例をさらに挙げていきましょう。

変数の型



 ところで一つ質問です。
 例えばメモリーのある場所に41hという16進データが入っていて、そこにSampleという名前が付いていたとします。
 それではこの41hというのは何を表しているのでしょうか?

 ああ?41hは41hに決まっているだろう!10進数なら65さ!

というのは早計です。前にも説明したとおりデータを数値で表すために様々な工夫がありました。実はこの65というのは2バイトで表される整数の上位の1バイト分かもしれないし、アスキーコードのAを表すための65かもしれません。

 すなわちメモリー上の数値はただの数値にしかすぎませんが、使う側から見れば様々な意味があるのです。しかし今までの説明だけではこのSampleという変数がどのような意味を持っているか分かりません。

 そこで変数の型という概念が登場します。
 これは言ってしまえば、

そのアドレスから始まるデータがどのような目的に使われ、どれだけの長さがあるかを定義したもの

です。

 例えば整数型という型があれば、そのデータは整数を表しています。前に説明したとおり、整数には上限があります。そのため整数型といっても以下のようにいろいろな種類があります。

byte符号のない1バイトの整数(0〜255)
shortint符号付きの1バイトの整数(-127〜128)
word符号のない2バイトの整数(0〜65535)
smallint符号のある2バイトの整数(-32768〜32767)
longint符号のある4バイトの整数(-2147483648〜2147483647)

 そして実際にある変数を使うぞ!と言う場合には

var Sample:longint; {Sampleという変数を符号付き4バイトの整数型で使うぞ!と}

 というようにその変数の型を指定する必要があるわけです。
(前項の例のbyteという呪文は実はこれでした)

 単純に足し算を行う場合でさえ、上の各型ではそのやり方は全く異なります。8ビットのCPUであれば2バイトの数なら2回、4バイトの数なら4回に分けて計算しなければなりません。負の数を扱うのも同様です。
 さらに実数を扱う場合には話はもっとややこしくなってきます。例えば実数には以下のような型があります。

single 4バイトの浮動小数点数(±1.5×10-45〜3.4×1038
double 8バイトの浮動小数点数(±5.0×10-324〜1.7×10308
currency 8バイトの固定小数点数(-922337203685477.5808〜922337203685477.5807)

 機械語の場合であればプログラマーが責任をもって各型の計算を行わなければなりませんが、高級言語の場合は型が分かれば自動的に処理してくれるようにできているのです。すなわち上記の型が何だったにしても同じ型同士であればX+Yと書けば足し算ができてしまうのです。

 なんだか当たり前のようですが、コンピューターは当たり前のことさえできないことは前の章を見ていただければ分かるはずです。当たり前のことができることが、すばらしい進歩なのです・・・

 また扱うデータは数値だけではありません。

char アスキーコードで表した1文字(1バイト)
string 任意の長さの文字列
boolean 真偽値 TRUE(1),FALSE(0)の二つの値を持つ

 のように様々な型が定義できます。

 ちなみに、string型の任意の長さって言うのは困るんじゃないかと思う方がいるかも知れません。でもあると便利です。文字列というのはあらかじめ長さが決まっていないことが多いからです。
 このあたりの処理は使用する高級言語によって違います。PASCAL言語では最初の1バイトが実は文字列の長さで、2バイト目から実際の文字列が入っている、といった処理をしています。C言語ではそのアドレスから0が入っている場所まで、というような処理をします。

 変数に型があるということは、それ以外に大きな利点を生み出します。というのは変数の型があるとプログラムの際の間違いが劇的に減ると言うことです。というのは、高級言語においては型が異なる変数同士の計算が単純にはできないようになっているのです。
 例えばXを整数型、Yを文字型とすると、うっかり X+Y と書いたりしたらエラーが発生します。

 考えたら分かるとおりに整数と文字を足すというのは全く意味のない行為です。しかし機械語レベルでは全て数値であるためにこのような計算もできてしまいます。その結果は何がなんだか分からないことになります。

 しかしここでエラーが出てくれれば、少なくとも何かおかしいことが分かって、つまらない間違いを未然に防ぐことができるわけです。


広い範囲に名前をつける:配列



 さて、変数というのは上記の通り大変便利な物ですが、それだけではまだ困ることがあります。

 例えば迷宮からの脱出の時に使った迷路のデータのことを思い出してください。
 あのときはアドレスの計算を行って、新しい位置を得ました。では変数を使って同じようなことができるでしょうか?

 ちょっと考えれば分かるとおりに、これは無理です。なぜならデータのアドレス番号を気にしなくていいようにと変数という概念を入れたのです。ここで再びアドレスを持ち出してきたら本末転倒してしまいます。
 しかしこういう操作が必要なのは明らかです。

 こう言うときに便利なのが配列というデータ形式です。

 配列とはその名の通り、ある型の変数がずらっと並んでいるものです。PASCALでは例えば次のように宣言します。

 var MAZE:array[1..215] of byte;

 これはMAZEという変数の宣言ですが、この変数はbyte型の変数が215個並んだ物だということを表してます。そして、例えば並んでいる変数の10番目の値を処理したい場合は、MAZE[10]というように書けばいいようになっています。

 これが便利なのはこれを使うとデータの前から何番目ということだけ知っていればいいことです。

 これがどれほどすごいことかというと・・・前の迷宮脱出プログラムでは、迷路のデータは0番地から入れていました。しかし実は、普通のコンピュータは0番地からは使えません(特別なプログラムが入っているためです)・・・ということにあとから気が付いたので直そうと思ったとします・・・

 そうです。気が遠くなりますね。あのプログラムはデータが0番地から入っているという前提で作られていました。それを変えようと思ったら、プログラムを書き換えなければいけません。
 でも配列にしておけばそういうことを気にする必要はありません。なぜならデータの場所はコンピュータが勝手に決めてくれるのですから。

 ところで、変数の並びとは一直線に並んでいるだけではないでしょう。例えば前の迷路の例では、各地点を座標と考えて、例えば(10,5)と表示した方がさらにわかりやすくなります。
 たいていの場合配列は、以下の例のように2次元(その気になれば何次元でも)の配列が作れるようになっています。

 var MAZE:array[1..15,1..15] of BYTE;

(10,5)の地点のデータがほしければ、MAZE[10,5]と書けばいいのです。


複雑な構造に名前を付ける:レコード型(構造体)



 データには更に他の性質を持ったものもあります。例えばあなたが以下のような項目のある小さな手帳を持っていたとします。

名前、電話番号、生年月日、B、W、H、済

 このデータは名前、電話番号は文字列です。生年月日やB、W、Hなどは数値でしょう。済というのは○×で表せればいいデータのようです。
 もちろんこれは一つだけでなくこういう構造をもった表がずらっと並んでいるわけです(男だったら項目は1000個ないといけません)

 こういう複雑な構造を持ったデータを単なる変数や配列で表そうとするとかなり面倒なことになります。
 やろうとすると以下のようになるでしょうか。

 var Name    :array[1..1000] of String; 
 var Tel    :array[1..1000] of String; 
 var BirthYear :array[1..1000] of Integer; 
 var BirthMonth :array[1..1000] of Byte; 
 var BirthDay  :array[1..1000] of Byte; 
 var B     :array[1..1000] of Byte; 
 var W     :array[1..1000] of Byte; 
 var H     :array[1..1000] of Byte; 
 var Done    :array[1..1000] of Boolean; 

 こうすると何が困るかというと、例えばこのデータの100番目の項目を200番目にコピーしようと思ったら、

 Name[200] := Name[100]; 
 Tel[200] := Tel[100]; 
 BirthYear[200] := BirthYear[100]; 
 ...

と全部の項目に関してプログラムを書かなければなりません。面倒くさそうですね。どうにかならないのでしょうか?

 こういうデータベース的なデータは大変良く出てきます。こう言うときのために高級な言語にはレコード型(C言語風の言い方なら構造体)というデータ形式があります。
 これを使うにはまずデータの項目を例えば以下のように定義しておきます。

 type GirlData = record 
  Name   :String; 
  Tel    :String; 
  BirthYear :Integer; 
  BirthMonth:Byte; 
  BirthDay :Byte; 
  B     :Byte; 
  W     :Byte; 
  H     :Byte; 
  Done   :Boolean; 
 end; 

 そして全体のデータを以下のように配列で宣言します。

 var MyLadies:array[1..1000] of GirlData; 

 これは変数MyLadiesとはGirlData型の変数が1000個並んでいる配列である、と読めます。
 こうするすると100番目の項目を200番目の項目にコピーするときは

 MyLadies[200]:=MyLadies[100]; 

と1行で済んでしまいます!

 データの各項目を参照したいときは例えば

 MyLadies[100].Name:='Ryoko Suehiro'; 
 MyLadies[100].W:=58; 

と言う感じでピリオドで区切ればいいようになっています。

まとめると・・・



 皆さんはこの辺の細かいところを覚える必要はありませんが、とにかく重要なのは、うまい名前の付け方をすると、それだけで作業がとても楽になる(ことがある)ということなのです。


前へ 目次へ 次へ