Version 4.05
ビット操作
「前回は2進数ってものについて紹介しました」
『なんかパズルみたいだったよねー』
「今回は、そのイメージをもっとしっかりしたものにしようと思います。え
っとまず、用語について。ビットって知ってる?」
『聞いたことはあるけど、よくしんない』
「ビットって言うのは、2進数で表示したときの〈桁の数〉。だから 00 な
ら2ビットね」
『あー、じゃー 0101 なら4ビットってこと?』
「そゆこと。つまり4ビットで16進数1桁ってことだね。さて次。 0001
を16進数で言うと?」
『 1 だよ』
「じゃ 0010 は?」
『えっと、 2 だね。ついでに言っとくと 0100 は 4 で 1000 は 8 だよ』
「そうそう、 8421 ってなってるからね。で、 0001 を〈ずらして〉 0010
にすることを〈ビットシフトする〉って言います」
『びっとしふと?』
「そう。〈シフト〉っていうのは〈ずらす〉って意味。ビットをずらすわけ」
『ってことは 0010 をビットシフトすると 0100 になるの?』
「そゆこと。あと左方向じゃなくて右方向にもシフトできるよ」
『できるよ、ってのは?』
「あー、そういうことがプログラムでできるってこと。やってみようか」
void BitShiftLeft()
{
char ch = 0x01; // 00000001
for( int iF1 = 0; iF1 < 4; iF1++ )
{
TRACE( "%X ", ch );
ch = ch << 1; // ここ。
}
}
// 1 2 4 8
『むむ、なんか難しそう』
「ひとつひとつね。まず char 型の変数を作って、 00000001 を入れます」
『 char って数字入れるのだもんね。で、 for だから繰り返しね』
「そう、4回繰り返し。繰り返すのは、 ch を16進数として表示するとこ
と、 << 演算子を使うこと」
『これ初見!』
「この << を使うと、左方向にビットシフトします」
『あ、これがさっき言ってた〈できる〉ってことね』
「 << 演算子は、左の数字を、右の回数だけずらします」
『この例だと1回だけずらすんだ。2回ずらすって、 0001 が 0100 になる
ってこと?』
「そういうこと。で、ここでは1回ずつずらしてるから、 ch の中身は 0001
0010 0100 1000 っていうふうにひとつずつずれていくわけ」
『だから結果が 1 2 4 8 ってことなんだ。でも当たり前よね』
「そう、そこが大事!」
『な、なに?』
「前も言ったけど、ビットそのものを直接見ることはできないわけ」
『あー、この例だと ch を 0001 みたいに表示できないってことね』
「そうそう。だから16進数で表示してイメージ沸かせるしかないんだけど」
『当たり前って思えるんなら、イメージがしっかりできてるってこと?』
「そういうこと。それが大事だから」
『ま、こういう例が見られればね』
「ちなみに今のは左シフト。右シフトは >> を使います」
void BitShiftRight()
{
char ch = 0x08; // 00001000
for( int iF1 = 0; iF1 < 4; iF1++ )
{
TRACE( "%X ", ch );
ch = ch >> 1; // ここ。
}
}
// 8 4 2 1
『今度は 1000 0100 0010 0001 ってなってくんだ』
「そういうこと。じゃ、次に進みます。フラグって知ってる?」
『ゲームするときにときどき聞くね』
「フラグっていうのは〈しるし〉のこと。たとえば RPG とかで、ボスを倒
すとストーリーが変化したりするでしょ」
『よくあるパターンね』
「こういうとき〈フラグが立った〉って言います。フラグって英語で〈旗〉
って意味。ボスを倒した印として旗が立つ、ってイメージかな」
『オフサイドぴぴーみたいな?』
「そういうこと。で、実際にホントに旗が立つわけじゃなくて、プログラム
の中では〈変数の値が変わる〉ってことを印にします」
『たとえば int の変数作って、 1 ならまだ倒してない、 -1 なら倒した、
みたいな?』
「そうそう、そういうこと。それをもっと効率良くしたのが〈ビットフラグ〉
ってもの」
『ビットフラグ?』
「 0000 の各ビットって、基本的にスイッチでしょ」
『うんうん』
「だからたとえば〈一番右の桁が、 0 ならまだ倒してない、 1 なら倒した〉
みたいなフラグにすることができるわけ」
『 0000 なら倒してない、 0001 なら倒したってことね。でも他の3桁が無
駄じゃん』
「そこは別のフラグに使えばいいでしょ」
『あ、つまりこうすれば、 char なら……えっと、8個のフラグが使えるっ
てことなんだ!』
「そういうこと。これなら効率的でいいでしょ」
『うん、いいいい。で、どう使うの?』
「〈ビット和演算子〉ってものを使います」
『びっとわ? べべんべんべん』
「そりゃ琵琶や」
『ぶぶー三味線だもん』
「分かんないって。で話を戻すと、 1000 と 0001 を組み合わせて 1001 に
したいってときは、どうすればいい?」
『足せばいいんじゃない? えっと、 8 と 1 だから足して 9 ! うん、
やっぱ足せばいーよね』
「じゃ、 1001 と 0001 を組み合わせて 1001 にしたいときは?」
『あれ? 1010 になんないの?』
「それぞれの桁は別のフラグなんだから、繰り上がりしちゃダメでしょ。も
ともとフラグが立っているときにさらにフラグ立てようとしたら、そのまま
立たせとくってこと」
『つまり 0001 と 0001 組み合わせても 0001 ってことね。これは足し算
じゃむりね。そこでビット和!』
「そゆこと。ビット和演算子は | のこと。 Shift キー押しながら Back
Space の左のキーを押せば出てくるから」
『ほほー、こんなマイナーなものが……』
「では試してみましょう」
void BitSum()
{
char ch
= 0x08 // 00001000
| 0x01; // 00000001
TRACE( "%X\n", ch );
// 9
// つまり 00001001
ch
= 0x09 // 00001001
| 0x01; // 00000001
TRACE( "%X\n", ch );
// 9
// つまり 00001001
}
『んーと、 char の変数 ch を作って、数字入れてるね』
「ここで、 1000 と 0001 を組み合わせた結果を ch の中に入れてます」
『その〈組み合わせ〉をするのが | ってことね。で結果が 1001』
「つまり | を使うと特定のビットだけを 1 にすることができます」
『〈特定のビット〉を変えるときって、 0001 を 0010 や 0100 にすればい
いってことだよね』
「そういうこと。で、その次に 1001 と 0001 を組み合わせてます」
『足し算なら 1010 になっちゃうけど、ビット和だから 1001 なんだね』
「ビット和が各ビットを操作できるってことが分かったね。ちなみにビット
和、実は前に使ったことがあるんだよ」
『ええっ!? ど、どーりでどっかで見たよーな気が』
「してないでしょ。 Ver 2.11 ( No.022 )で、こんなふうに使ってます」
MessageBox( "あいうえお", "かきくけこ"
, MB_YESNO | MB_ICONQUESTION );
『あ、これダイアログ表示するのだよね。 MB_YESNO って【はい】と【いい
え】のボタンを付けるので、 MB_ICONQUESTION ってアイコンをはてなマーク
にするのだよね』
「そうそう。こういう〈状態を渡す〉ときは、たいがいこういうふうにビッ
ト和で渡します」
『つまり MB_YESNO とかがビットフラグになってるってことね』
「そういうこと。じゃ、今日最後は、 & について」
『 & って〈アンド〉だよね』
「ま、それは考えない方がいいかな。 & もビット操作をする演算子。ま、
とりあえずこれを試してみて」
void BitMultiply()
{
char ch
= 0x01 // 00000001
& 0x08; // 00001000
TRACE( "%X\n", ch );
// 0
ch
= 0x09 // 00001001
& 0x08; // 00001000
TRACE( "%X\n", ch );
// 1
// 00001000
}
『えっと、上は 0 、下は 1 』
「 & は、ビットが両方とも 1 だと 1 に、それ以外は 0 にするって演算子。
上は、どのビットも合ってないでしょ」
『あ、下は右から4ビット目が両方とも 1 だから、そこだけが 1 になって
るんだ。でもこれって使えなくない?』
「これはね、フラグが立ってるか立ってないかをチェックするの」
void CheckBitFlag( char p_ch )
{
if( p_ch & 0x1 ) // 00000001
{
TRACE( "赤" );
}
if( p_ch & 0x8 ) // 00001000
{
TRACE( "青" );
}
TRACE( "\n" );
}
void SendBitFlag()
{
CheckBitFlag( 0x1 );
// 赤
CheckBitFlag( 0x8 );
// 青
CheckBitFlag( 0x1 | 0x8 );
// 赤青
}
『あ、 if って 0 以外だと {} の中に入るんだもんね。 & で立ってるかど
うか調べられるんだ』
「こうすることで、ひとつの変数にいっぱいのフラグを格納できるってわけ
だね」
/*
Preview Next Story!
*/
『でもさ、フラグってホントは〈フラッグ〉じゃないの?』
「そういえばそうだね……」
『ねー〈ビットを 0 にする〉のはどうすればいいの?』
「そんなめったに使わないの憶える必要ないよ……」
『なんか投げやりー』
「というわけで次回」
< Version 4.06 正と負! >
『につづく!』
「業界には不思議なことが多いしね……」
『何黄昏てんのよ』