Version 4.06
正と負!
「ビット編最後は〈正と負〉について」
『それってプラスとマイナスのこと?』
「そう。さて、まずはおさらいから。 char って16進数何桁入るんだっけ」
『2桁だよ。 0x11 みたいな感じ』
「16進数1桁は、2進数で何桁だっけ」
『4桁。 0x5 が 0101 みたいな。ってことは、 char は2進数8桁分って
ことだね、 01010101 が 0x55 で、えーっと…… 85 みたいに』
「そういうこと。それを踏まえて、次の関数を試してみましょう」
void BitShift8()
{
char ch = 0x01; // 00000001
for( int iF1 = 0; iF1 < 8; iF1++ )
{
TRACE( "%d ", ch );
ch = ch << 1;
}
}
// 1 2 4 8 16 32 64 -128
『あ、この前見たのと似てるね』
「この前は4回しかシフトしなかったけど、今回は8回、だから 00000001
から 10000000 までシフトする例」
『 00000001 が 1 で、 00000010 が 2 で、そのあと 4 8 16 32 64 -128
って、なんで 128 だけマイナスなの!? あ、これがミソなんだ』
「そういうこと。 char の変数は、サイズが8ビット。どうがんばっても、
8ビット分の情報しか入らない」
『8ビットって、メモリの1マスだもんね。もしはみ出たら、他の変数にと
か邪魔しちゃうかもしんないもんね』
「単純に、 11111111 つまり 0xFF を10進数に直すと?」
『 16 * 15 + 15 だから 255 だね』
「ってことは、 00000000 から 11111111 まで全部使うと、 0 から 255 ま
で表せるってことだ」
『そだね』
「マイナスはどうする?」
『あ、そういえば』
「〈この数はマイナスですよ〉っていう情報も、8ビットの中に入れなきゃ
いけないでしょ。それをどうするか」
『どうするの?』
「そこで、ビットひとつを〈プラスかマイナスかのフラグ〉にする、ってこ
とになります。そのフラグは一番左の桁。 00000000 だとプラス、 10000000
だとマイナスね」
『あ、 10000000 ってだから -128 だったんだ!』
「そういうこと。一番左の桁を正負のフラグにして、あとの7桁を数字を表
すのに使います」
『ってことは、正の数は 01111111 まで……だから 127 まで表せるってこ
とだね。う”、一気に半分になっちゃった』
「その分、マイナスも表せるってことだからね」
『……変よ! なんで 10000000 が -128 なの? -0 とか -1 とかなりそ
うなのに』
「 -0 はないでしょ。 -1 は 11111111 だよ。で、 -2 は 11111110 ね」
『えーっ!? 逆になるんだー、なんかわけわかんない……』
「分かんなくていいよ、これは計算する必要とかあんまりないから」
『そなの?』
「そなの。しっかり憶えて欲しいのは、一番左の桁が正負のフラグってこと」
『確かにこれは、知ってないと怖いよね』
「ちなみにマイナスの最大値は -128 だから」
『あー、 11111111 から減らしていけば 10000000 になって -128 になるも
んね。さらに減らすと 01111111 で 127 になっちゃうし』
「そういうこと。 char 型変数の中に入るのは 127 から -128 ってことだね」
『あ! これが Ver 4.02 ( No.052 )で言ってた〈 -128 から 127 の間
の数字しか、 char 型変数には入らないから〉の理由なんだ!』
「そういうこと。理由が分かるって大事だからね」
『うん、こーゆーの分かるのうれしいもん』
「さてさて、 char は 127 から -128 しか使えないけど、実は 255 から 0
まで使う方法があります」
『それって一番左の桁を正負のフラグに使わない、ってことだね?』
「そゆこと。そういうのを〈符号なし整数値〉って言います」
『プラスだけなんだ』
「限界ギリギリの数字を使いたいときや、純粋にビットフラグだけとして使
いたいときによく使われるかな。じゃ、まずこれから」
void Normal()
{
char ch = 255;
}
『あ、ビルドしたらエラー出た』
warning C4305: 'initializing' : 'const int'から'char'へ切り詰めます。
warning C4309: 'initializing' : 定数値が切り捨てられました。
「エラーじゃなくて警告だね。一応 char 型に 255 は入るんだけど、 char
の範囲内じゃないから切りつめられちゃうわけ」
『だから〈あかんよー〉って言ってるんだ』
「では次」
void Signed()
{
signed char ch = 255;
}
warning C4305: 'initializing' : 'const int'から'char'へ切り詰めます。
warning C4309: 'initializing' : 定数値が切り捨てられました。
『同じエラー出た。あれ、 signed って?』
「これは〈さいんど〉って読みます。これが付いていると〈符号あり〉って
見なされます。だから signed char には 127 から -128 まで入るってこと
だね」
『……それってこれまでと一緒じゃん』
「そゆこと。ただ、それは VC だから」
『どゆこと?』
「開発環境によっては、デフォルトが signed とは限らないからね。 VC は
何も付けないと自動的に signed が付いたのと同じになるってこと」
『前もそーゆーのあったね』
「プログラミングにはそういうのがつきものだから注意してね。では本命、
符号なし整数値です!」
void UnSigned()
{
unsigned char ch = 255;
TRACE( "%u\n", ch );
// 255
}
『あ、 unsigned ってのがそうなんだ』
「そう、これは〈アンサインド〉って読んで、これが付くと〈符号なし〉に
なります。だからこれは警告が出ません」
『ほー。あれ、 TRACE() が %u になってる』
「 %d は〈符号あり整数〉として表示するのだからね。〈符号なし〉として
表示するのは %u の方」
『ちょっと複雑ねー』
「まーね。この辺は実際複雑だから」
『どゆこと?』
「 signed char に -1 入れるのと、 unsigned char に 255 入れるのって、
ビット的には同じでしょ」
『うん、どっちも 11111111 だよね』
「つまりこれは〈符号あり〉ってみなすか〈符号なし〉って見なすかの問題
ってことだね」
『みなしの問題、つまりどう捉えるか、どういうものなのかって考えるかっ
てことだよね』
「たとえば」
void Compare()
{
char ch = -1;
unsigned char uch = ch;
if( ch < uch )
{
TRACE( "%d < %u\n", ch, uch );
}
}
// -1 < 255
『あ、 char のを unsigned char に入れてるんだ。で、 if で比べて……
そっか、 unsigned char のに入れると -1 が 255 になっちゃうから、そっ
ちの方が大きくなっちゃうんだ』
「ビット的には同じだけど、〈型〉が違うから比較方法が変わっちゃうんだ
よね」
『型?』
「そう。 int とか char とか unsigned char みたいな〈変数を作るときに、
その変数がどんな性格か〉を決めるものを〈型〉っていいます」
『つまり、 char と unsigned char は、メモリの上じゃおんなじ1マスな
のに、 char はマイナスあり、 unsigned char はマイナスなしってゆー
ふーに、性格が変わるってことね』
「そういうこと。 < なんかの演算子は、掛かる変数がどんな型かで比較方
法が変わるわけ。今の例みたいにね」
『プログラミングはみなしの世界。型はその〈どうみなすか〉を決めるもの
だから、大事ってことよね』
「そういうことだね。この部分、とっても大事だから」
『そんなに大事?』
「大事だね。こういう部分に問題が起きやすいから」
『たとえば?』
「たとえば今の比較の問題。後から出てくるけど、普段は char の方がよく
使うのに、実際の処理は unsigned char の方がよく使うとかあるんだよね」
『どゆこと?』
「入ってる数字は 0 から 255 なのに、それ入れるのは char の変数ってこ
と。こういうとこ勘違いするとあいたーってことになりかねないからね」
『そういうのの対処法は?』
「どこが問題になりやすいのかってことを気にしておくことだね。符号問題
は、比較が一番の問題点だから、比較するときに気を付けるとかね」
『 < を使う時に〈あ、符号大丈夫かな〉って考えるんだ』
「あとは余裕だね。 255 まで入るから unsigned char ってよりは、 int
使っちゃう方がいいとかね」
『なるほど、余裕持たせれば面倒なこと考えなくていいんだ』
「実際にはそう簡単には割り切れないし、どういう場面でどっちを使えばい
いって議論はずっとされてきてて、決着が付いてなかったりするんだよね」
『つまり〈これすればOK!〉みたいなのってないってこと?』
「そういうこと。火美ちゃんは、今日教えた〈みなしの世界〉ってどう思
う?」
『ヘン! ってゆーかアブナイ、かな。たとえばさ、1って、1等ならいい
けど、成績で1って良くないじゃん、そーゆーふーに、場合場合で意味変わ
るのってなんか怖いな』
「その怖い世界がプログラミングの世界。そういう点を自覚するのも、大事
かな」
『なんかヤバイ世界に足突っ込んだ?』
「1年経って何を今さら」
/*
Preview Next Story!
*/
『ってことはさ、世の中のコンピューターって、全部こんな感じ?』
「こんな感じ」
『うわー、なんかそう考えると怖いね』
「って、火美ちゃんだってこんな感じじゃん」
『ひーそうだったー!』
「というわけで次回」
< Version 4.07 short とバイトオーダー >
『につづく!』
「火美ちゃんもみなしの世界に生きてるんだよ」
『……じゃー水希ちゃんを美形ってみなすこともできるんだ』
「おい」