C++ ⇒ VBA 書いて覚えるための初心者自己中記事

C++ ⇒ VBA 勉強の履歴を付けるというかノート代わりに使ってます

C++ ビット演算 書いて覚えるための初心者自己中記事

二進数の演算にはビット演算というものがある

五種類あって

AND 論理積

OR 論理和

XOR 排他的論理和

NOT 論理否定

ビットシフト

 

これらは演算子オーバーロードされない限り整数しか扱えない。

 

ANDの演算子

&

二項演算子だ。

 0011

&)0101

ーーーーー

 0001

 

上下の数値に対してANDは両方とも1の時だけ1を出している。

 

これを利用して

 

 01111010

&)00001111

ーーーーーーーーー

 00001010

 

とする。取り出したいビット部分は1で。

必要ないビット部分は0で計算させると

ほしいビット部分が抜き出される。

 これをマスキングという。

 

 

 ビット演算子の優先順位は低い

a & b == c

の場合など

a & (b == c)

こうなる。 

 

 

 OR(論理和)の場合

演算子は |

二項演算子

 0011

|)  0101

ーーーーー

 0111

両方、またはどちらかが1の場合は1を出している。

 

これを利用して

 01001101

|) 10000111

ーーーーーーーーー

 11001111

 

とする。

上書きしたい部分は1で、

そのまま残したい部分は0でいける。

 

 

 XOR(排他的論理和)の場合

演算子は ^

二項演算子

 0011

^) 0101

ーーーーー

 0110

 

片方が1の場合は1

それ以外は0

上下で違っていないと気が済まない感じ

 

これを利用して

 01111010

^) 00001111

ーーーーーーーーー

 01110101

 

となる。

反転させたいビット部分には1を

そのままにしたい部分には0を。

ビット反転というらしい。

 

 

 NOT(論理否定)の場合

演算子は ~

単項演算子(ビット演算子で唯一)

~)01

ーーー

 10

 

ただ反転した。

 

これを利用するにはANDも使って

~)00011111

ーーーーーーーーー

 11100000

 

反転させてからANDでやったみたいにすると

 01111010

&)11100000

ーーーーーーーーー

 01100000

 

NOTをつかうとANDの結果が逆になる

 

 

ビットシフトの場合

演算子は >> (右シフト)   << (左シフト)

 二項演算子

 

00010101

>>)       2

ーーーーーーーー

00000101

 

 

00010101

<<)       4

ーーーーーーーー

01010000

 

 シフトしている。

溢れたビットは切り捨てられる。

 

負の数を右シフト>> するとビットの無くなる部分が1で埋められる。

10010010

>>)       4

ーーーーーーーー

11111001

 

これを算術シフトという。

また、一番上を0で埋めることを論理シフトという。

 

 算術シフトは

負の数を2の補数という形式で表現している環境

で使われる環境依存

???

 

 

実際の使用例

 

int main() {
	int x = 105054;
	for (int i = 1,count = 1; i <= x; i <<= 1,++count) {// i <<= 1 で1桁づつ左にビットシフト
		if ((x & i) == 0) {// 左に1づつビットシフトしているi とx を&して結果が1ならxのその桁は1
			cout << count << "ビット目が0" << endl;
		}
		else {
			cout << count << "ビット目が1" << endl;
		}

} system("pause"); }

//output
1ビット目が0
2ビット目が1
3ビット目が1
4ビット目が1
5ビット目が1
6ビット目が0
7ビット目が1
8ビット目が0
9ビット目が0
10ビット目が1
11ビット目が0
12ビット目が1
13ビット目が1
14ビット目が0
15ビット目が0
16ビット目が1
17ビット目が1

 

慣れないと非常にややこしいな・・。

 

 

次。

ビットフラグ

上記の感覚でビットごとにフラグとしての役割を持たせる。

 

int Bit(int x) {
	return 1 << x;
}
 
const int SHOW_X = Bit(0);
const int SHOW_Y = Bit(1);
const int SHOW_Z = Bit(2);
 
void Show(int flags) {
	cout << (flags & SHOW_X ? 'X' : 'x')
		 << (flags & SHOW_Y ? 'Y' : 'y')
		 << (flags & SHOW_Z ? 'Z' : 'z')
		 << endl;
}
 
int main() {
	Show(0); // 0
	Show(SHOW_X); // 1
	Show(SHOW_Y | SHOW_Z); // 11
	Show(SHOW_X | SHOW_Y | SHOW_Z); // 111
 
	system("pause");
}
//output
xyz
Xyz
xYZ
XYZ

Show();

入れる前にint変数 flags に入れたほうがすっきるする。

 

int main() {
	int flags = SHOW_X | SHOW_Y | SHOW_Z;
 
	Show(flags); // 1
 
	system("pause");
}

 

このflags に対してフラグを追加したり削除したりしたい。

 

int main() {
	int flags = SHOW_X;
 
	flags |= SHOW_Y;//SHOW_Yを追加した
 
	flags &= ~SHOW_Y;// AND NOT でSHOW_Y を削除した
 
	flags ^= SHOW_Y;//XOR でSHOW_Yを反転させた
 
	Show(flags); /
 
	system("pause");
}

 これらはORで複数まとめてもOK

 

 

 ここまで