モーションコントロール系のソフトを作っている中で、ビット演算が多く、自習と備忘録。
間違いや、より良い手法がありましたらご指摘ください。
[2016/05/08: int → unsigned intへ変更しました]
Cでのビット演算子
AND
a = a&b;
a &= b;
a | b | new a |
---|---|---|
0 | 0 | 0 |
1 | 0 | 0 |
0 | 1 | 0 |
1 | 1 | 1 |
ANDは両方が真である場合のみ、真を返し、それ以外は偽を返す。つまり、ビットが1&1の時のみ、1になる。ステータスワードなんかのビットを落とすときに使える。
OR
a = a|b;
a |= b;
a | b | new a |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 1 |
ORはどちらかが真であれば真を返し、両方が偽である場合のみ偽を返す。つまり、ビットのどちらかが1であれば、1を返す。ビットを立てるときに使える。
XOR
a = a^b;
a ^= b;
a | b | new a |
---|---|---|
0 | 0 | 0 |
1 | 0 | 1 |
0 | 1 | 1 |
1 | 1 | 0 |
XORは、片方が真、もう片方が偽である場合のみ真を返す。つまり、片方が1でもう片方が0である場合に、1を返す。ビットを反転させるのに使える。
NOT
a = ~a;
a | new a |
---|---|
0 | 1 |
1 | 0 |
NOTは真であれば偽を返し、偽であれば真を返す。つまり1なら0、0なら1を返す。ワードの各ビットへアクセスするというところでいくと、あんまり使いみちが思い浮かばない。。。重要なのは、論理演算子は(NOTに限らず)、全ビットが対象になるというところがミソ。
ビットシフト
a<<b; //左シフト
a>>b; //右シフト
基本は操作対象変数aのビットをbだけそれぞれの方向にずらす操作。1ビットシフトの動きは次の通り。
左シフト:最上位ビットを捨て、残りのビットはひとつ上のビットへ移動。最下位ビットには0。
右シフト:最下位ビットを捨て、残りのビットはひとつ下のビットへ移動。最上位ビットには0(負数の場合は1が入るとか入らないとか。。。)。
(2016/05/08: 符号付きの場合の結果は不定とのご指摘をいただきました。ありがとうございました)
よく使うビット演算
特定ビットの取り出し
unsigned int GetBit(unsigned int word, unsigned int bitNum)
{
//ターゲットのビットを最下位ビットまで持ってくる
word >>= bitNum;
//0x01とANDしてやる。最下位ビット以外はすべて0になり、最下位ビットはそのまま
word &= 0x01;
return word;
//シンプルに書くならまとめて。#defineでもいいかもしれない。
// return ( (word >> bitNum) & 0x01);
}
特定のステータスビットをチェックするのに使う。
特定ビットON
unsigned int BitON(unsigned int word, unsigned int bitNum)
{
unsigned int mask = 0x01;
//対象ビット位置まで左シフト
mask <<= bitNum;
// maskとOR
word |= mask;
return word;
// simpler...
// return ( word |= ( 0x01 << bitNum ) );
}
特定ビットOFF
unsigned int BitOFF(unsigned int word, unsigned int bitNum)
{
unsigned int mask = 0x01;
//対象ビット位置まで左シフト
mask <<= bitNum;
//mask bit反転
mask = ~mask;
// maskとAND
word &= mask;
return word;
// simpler...
// return ( word &= ~( 0x01 << bitNum ) );
}
特定ビットの反転
unsigned int ChangeBit(unsigned int word, unsigned int bitNum)
{
unsigned int mask = 0x01;
//対象ビット位置まで左シフト
mask <<= bitNum;
// maskとXOR
word ^= mask;
return word;
// simpler...
// return ( word ^= ( 0x01 << bitNum ) );
}
フラグ代わりに使っているビットのON/OFFに使ったりする。
ビットの連動
unsigned int InterlockBit(unsigned int inputState, unsigned int outputState, unsigned int inputBit, unsigned int outputBit)
{
// ビットの取り出し
unsigned int input = inputState & (0x01 << inputBit);
unsigned int output = outputState & (0x01 << outputBit);
// 状態比較して状態が異なればビット反転
// inputとoutputのXORで状態が異なれば0x01のマスクができる
// --> if (input != output){ outputState ^= (0x01 << outputBit) } と同じ処理になる
outputState ^= ( (input ^ output) << outputBit );
return outputState;
}
あるビットが変化したらそれに応じて別のビット列のビットを連動して変化させる。I/Oを管理しているような場合に入力が変化した場合に出力を連動させるときに使う。