Version 4.07
short とバイトオーダー
「さて、 char にも飽きてきたと思うんで違う型も見てみましょう」
『型ってゆーと、 int とか char とか、あとクラスってのとかあるけど、
他にもいっぱいあるんだ』
「結構あるね。今日は short っていうのを見ます。この前の復習になるけ
ど、 char に入る数字の範囲は?」
『 -128 から 127 。 unsigned char だと 0 から 255 ね』
「そうでした。つまり8ビット=1バイトじゃこれだけの種類しか数字を表
現できないわけだ。火美ちゃんなら、これ以上表現したいときにはどうす
る?」
『1バイトって、つまりメモリの1マスだったんだよね。だったら2マス使
うとか?』
「そういうこと! それが short 型」
『なるほど、そういうふうに用意されてるんだ』
「 short 型は2バイト使って整数を表現できます。さて問題。2バイトっ
てことは入る範囲は?」
『えーっと……』
「あ、 unsigned char から考えた方が簡単かも。 short にも signed と
unsigned があるから」
『んじゃ、 char の 255 って、ビットだと 11111111 で16進数だと 0xFF
で 15 x 16 + 15 = 255 だったんだよね』
「2バイトだと倍になるから?」
『 1111111111111111 で 0xFFFF でしょ……』
「そこまでしたら計算機の方が楽でしょ。【関数電卓】モードで16進にし
てから FFFF って入れて、10進に戻すと」
『 65535 、簡単だね』
「ちなみに 1111111111111111 = 16ビット = 2の16乗 = 65536 、で 0
の分があるから1引いて 65535 って求め方もあるかな」
『なんで16ビットだと16乗?』
「 Ver 4.03 ( No.053 )で言ったでしょ、1桁増えれば2通りできる、つ
まり1ビット増えたら2を掛ければいいわけ」
『そういえば。あんときはオンとおふだったけど』
「数字だけ見ると数学みたいだけど、基本的にはパズルだからね。あと
256 x 256 = 65536 で1引くって方法も」
『それはどーゆーの?』
「右1バイトが256通り。左1バイトが256通り。全部で何通り?」
『あー、組み合わせってヤツよね。で、掛けて 65536 通りなんだ』
「これもパズルだね。えっと、話それたけど」
『 unsigned short には 0 から 65535 まで入る! だよね』
「そうそう。 signed short は1ビットをプラスかマイナスかのフラグに使
うから?」
『1ビット少なくなって15ビットになるんだ。あ、こっちの方だとさっき
の〈16乗〉ってのの方が楽だね』
「ちなみに計算機だと2進モードにして 111111111111111 って入れてから
10進モードにすれば」
『 32767 だ!』
「そう、でもそれは上限。下限は?」
『んーと、 char の時って、上限のに1足してマイナスにしたのだけど、お
んなじ方法でいい?』
「そうだよ、プラスの場合とマイナスの場合、両方とも15ビット分あるわ
けだからね。1足すのは、プラスの方は0を表現するけど、マイナスの方は
0を表現しなくていいから、その分ね」
『ふと思ったんだけど、マイナスの方に0入れてもいいんじゃない?』
「 signed と unsigned でビットが変わっちゃうでしょう」
『あ、そういえば。だからプラスの方に合わせてあるんだ』
「そういうことだね。さて、 short の範囲は?」
『 -32768 から 32767 まで、だね』
「そういうこと。これをプログラムで見てみようか」
void View_short()
{
short sh; // short 型変数。
sh = 32767;
sh = 32767 + 1; // 警告。
sh = -32768;
sh = -32768 - 1; // 警告。
}
『えーっと、1行目は short 型の変数を作ってるんだよね。これはいつも
char で作ってたのと同じことだよね』
「そう。で、次の行は上限の 32767 を入れてます。これは大丈夫」
『その次の 32767 + 1 はつまり上限を超えるのを入れてるんだ。で、こん
なエラーが出ちゃった』
warning C4305: '=' : 'const int' から 'short' へ切り詰めます。
warning C4309: '=' : 定数値が切り捨てられました。
「 warning は【警告】だから、ビルド自体は成功してるからね。でも〈な
んか間違ったことしてるっぽいよ〜〉って感じたから」
『VCが警告出したんだ。あとのふたつは、同じことを下限でしてるんだよ
ね』
「そういうこと。これで short の範囲は分かったかな?」
『うん、大丈夫でしょ。 short も楽勝!』
「ってわけにはいかないんだよねー。さて、次に進んで、この関数を試して
みましょう」
void short_inMemory()
{
short sh = 0;
TRACE( "%X\n", &sh );
sh = -1; // ここにブレークポイントをセットしてください。
sh = 1;
}
「この関数の中の sh = -1 の行にブレークポイントをセットしてね」
『はい、手のひらマークっと。んでビルドして実行!』
「2行目の TRACE() は何してる?」
『 &sh 、あ、変数の前に & 付けると〈メモリのどこに変数があるか〉って
のになるんだよね』
「〈アドレス〉ね。とゆーわけでメモリウィンドウ開いて」
『開き方は Ver 4.02 ( No.052 )を見てねってことで、開いて上のとこに
アウトプットウィンドウの数字を入れてリターン!』
「その部分どうなってる?」
『 00 00 だって。あ、 sh の中 0 だからだ!』
「それと、 00 00 って2マス、つまり2バイト分ってこともね」
『そっか、 char は1バイトだったから1マスだったけど、 short って2
バイトだから2マスなんだ』
「それを確認したら1行進めて」
『 sh に -1 を入れれば当然 FF FF 、うんなったよ』
「じゃさらに1行進めて」
『 sh に 1 を入れて 01 00 ……ってなんで!? 00 01 じゃないの!?』
「今回のポイントはここ。実は、メモリ上では【下位1バイト】が先、【上
位1バイト】が後に来るんです」
『えええっ!? なんかスゲー混乱する!!』
「もひとつ例を見てみようか」
void Shift_short()
{
short sh = 1;
TRACE( "%X\n", &sh );
for( int iF1 = 0; iF1 < 16; iF1++ ) // ここと、
{
TRACE( "%d ", sh );
sh = sh << 1; // ここにブレークポイント。
}
}
「で、さっきと同じようにまずメモリウィンドウ見て」
『って言ってもたいがいアドレスって同じだよね。ひとつめ止まってメモリ
監視スタート! ううっ、 01 00 になってるー』
「じゃ【実行】コマンドを1回ずつゆっくりと繰り返していってみて」
『ぽち。あ、ふたつめのポイントに止まるんだね。 for だから繰り返しで、
つまりビットシフトする状態をメモリで追っていけばいいんだよね』
「そういうこと。整数値はどうなってる?」
『 1 2 4 8 16 って char の時と同じ』
「メモリは?」
『…… 01 00 、 02 00 、 04 00 、 08 00 、 10 00 、あ、1バイトの中
じゃフツーに繰り上がるんだね、ちょっと安心』
「そのまま進めてくと……」
『 128 のとき 80 00 、そして……あーっ!! 256 のときに 00 01 なん
かになりやがった!!』
「左右のバイトを逆に考えれば、フツーでしょ?」
『あー、うー、それは分かるんだけどさ、気持ち悪い〜』
「ま、最初は誰だってそう。そのまま進めてくと?」
『 2048 で 00 08 、その次 4096 で 00 10 、んではしょって 16384 で
00 40 、 -32768 で 00 80 。あ、 signed だからだね』
「つまり符号フラグがそこにあるってこと」
『う”、そういえば……なんか頭がごちゃごちゃする〜!』
「でもさ、ビットシフトはフツーにできたでしょ?」
『あ、そういえば。ビットシフトしたら左行っちゃいそうなもんだけど』
「整数だってちゃんと表示されてるし」
『うんされてる。これってもしかして、みなしってやつ?』
「そういうこと。メモリの中じゃ、こういうふうに特殊な置かれかたしてる
けど、実際には 1 は 0000000000000001 って考えてね」
『 0000000100000000 じゃないんだね。メモリだけ特別ってことなんだ』
「だから、ビットシフトしたり整数値として取り出したりするときはそうい
うの気にしなくていいから」
『なーんだ、じゃープログラム組む時って気にしなくていいんじゃない』
「そうもいかないんだよね」
『げげ』
「実は、こうなってるのはウィンドウズ系くらいなんだよね。マックとかは
普通に 最初に上位バイト、次に下位バイトってなってるから、他のコン
ピューターのファイル扱うときとかは」
『もしかして変換とかするの!? イヤー!』
「こういう〈変数をメモリに置いたとき、上位バイトと下位バイトがどの方
向に並ぶか〉を〈バイトオーダー〉って言います」
『てんちょー仕事辛いっすよー、社員増やしてくんない?』
「仕方ないなー。人事課長、バイト1人追加ねってそのオーダーちゃうわ。
order は〈順番〉って意味ね」
『バイトの並び順が違うってことなんだー』
「バイトオーダーのうち、今やったへんてこなのを〈リトルエンディアン〉、
普通の並び方を〈ビッグエンディアン〉って言います」
『変な名前ー』
「もはや嫌いモードですね」
『嫌い嫌い大っ嫌い! ってゆーか、なんでわざわざそんなへんてこな方法
にしてんの?』
「たとえばさ、 4 + 16 を計算する時って、まず 4 + 6 を計算するでしょ」
『そだね、繰り上がりがあるもんね』
「でもそれって変じゃない? 数式って左から右に見るのが普通なのに、繰
り上がりがあるから右から左って」
『……つまり、そんために 4 + 61 ってして計算する、ってことがリトルエ
ンディアン的考えってこと?』
「そういうこと。計算をするのは、もちろんコンピューター。リトルエン
ディアンはコンピューターにとっては自然な方法なのかもね」
『うー』
「さてまとめ。 short 型変数のサイズは何バイト?」
『2バイト16ビット。 -32768 から 32767 まで入るよ』
「で、バイトの並びは?」
『ちっこいバイトが最初に来て、大きいバイトが次にくる! だから 1 が
01 00 なんだねー』
「でも普通に扱うときはそういうこと考えなくていい、からね」
『はぁい』
/*
Preview Next Story!
*/
『リトルエンディアンなんて大っ嫌い〜!』
「確かに混乱するのは確かだけどね」
『水希ちゃんも混乱した?』
「そりゃもちろん。初めて知ったときはなんじゃこりゃって」
『プログラマーになるには誰もが乗り越えなきゃいけない壁なのね』
「というわけで次回」
< Version 4.08 色々な型 >
『につづく!』
「これからも驚かされることいっぱいあるよー」
『ひいいいいい! もしかして新手の怪談!?』