フラグの取得、設定(追加)、解除を行います。
理解しやすくするために0~9の数値に該当するビットを対象に、そして比較しやすいように桁数を4桁に統一し、話を進めます。
2進数対応表 |
10進数 | 2進数 |
0 | 0000 |
1 | 0001 |
2 | 0010 |
3 | 0011 |
4 | 0100 |
5 | 0101 |
6 | 0110 |
7 | 0111 |
8 | 1000 |
9 | 1001 |
ビット演算子 |
演算子 | 説明 |
& | 論理積 |
| | 論理和 |
^ | 排他的論理和 |
~ | 反転 |
ビット演算表
ビット | & | | | ^ |
0 | 0 | 0 | 0 | 0 |
0 | 1 | 0 | 1 | 1 |
1 | 0 | 0 | 1 | 1 |
1 | 1 | 1 | 1 | 0 |
10進数の「2」を出力してみます。
出力される結果を見やすくするため、2進数はPadLeftを使用し、4桁で揃えています。
int flag = 2; //0010
Console.WriteLine(
"10進数 : {0}\n 2進数 : {1}\n\n",
flag,
Convert.ToString(flag, 2).PadLeft(4, '0')
);
Result
10進数 : 2
2進数 : 0010
フラグの取得
フラグが立っているか否かを調べます。
フラグを取得する式
x & y
ビット演算子「&」は"x"と"y"の両方のフラグが立っている場合に1となります。
Example
3 & 2
↓
0011 & 0010
↓
結果: 0010
上記の場合、右から二番目の値だけが"1"なのでそれのみを残し、他は"0"となります。
これによってフラグの値のみを抽出できます。
Example
int flag1 = 2;//0010
int flag2 = 3;//0011
Console.WriteLine(flag1 & 2); //2
Console.WriteLine((flag1 & 2) != 0); //True
Console.WriteLine(flag2 & 2); //2
Console.WriteLine((flag2 & 2) != 0); //True
10進数の「2」、「3」ともに2番目のフラグが立っているのでTrueを返します。
フラグの設定
フラグが立っていない場合、フラグを設定します。
フラグを設定する式
x | y
ビット演算子「|」はどちらか一方、あるいは両方のフラグが立っていれば1となります。
Example
int flag1 = 2;//0010
int flag2 = 3;//0011
int flag3 = 4;//0100
var ret1 = flag1 | flag2;
Console.WriteLine(ret1); //3
//2進数に変換します。
Console.WriteLine(
Convert.ToString(ret1, 2).PadLeft(4, '0'));
//0011
var ret2 = flag2 | flag3;
Console.WriteLine(ret2); //7
//2進数に変換します。
Console.WriteLine(
Convert.ToString(ret2, 2).PadLeft(4, '0'));
//0111
var ret3 = flag3 | flag1;
Console.WriteLine(ret3); //6
//2進数に変換します。
Console.WriteLine(
Convert.ToString(ret3, 2).PadLeft(4, '0'));
//0110
フラグの解除
フラグが立っている場合、フラグを解除します。
フラグを解除する式
x & ~y
まず「~」を使用して反転させます。
例えば10進数の「2」を反転させると
「0010」→「1101」(4桁揃え)
その後、&演算子を使用し、論理積を求めます。
Example
int flag = 2;
int xor = (byte)~flag;
Console.WriteLine(xor);//253
//2進数に変換します
Console.WriteLine(
Convert.ToString(flag, 2).PadLeft(4, '0'));
//0010
Console.WriteLine(
Convert.ToString(xor, 2).PadLeft(4, '0'));
//11111101
//論理積を出力します。
Console.WriteLine(2 & xor); //0
Console.WriteLine(2 & ~2); //0
フラグを使う具体例
もう少し具体的な例を挙げてみます。
権限を設定することを想定し、以下のようなenumを作成してみます。
[FlagsAttribute]
enum PermissionFlags
{
None = 0,
Read = 1,
Create = 1 << 1,
Write = 1 << 2,
Delete = 1 << 3,
All = 1 | 1 << 1 | 1 << 2 | 1 << 3
}
上のPermissionFlagsを使用して権限の取得、追加、削除を行ってみます。
var p = PermissionFlags.Create | PermissionFlags.Read;
Console.WriteLine(p);
//Read, Create
//取得
Console.WriteLine((p & PermissionFlags.Create) != 0);
//true
//追加
p |= PermissionFlags.Delete;
Console.WriteLine(p);
//Read, Create, Delete
//削除
p &= ~PermissionFlags.Create;
Console.WriteLine(p);
//Read, Delete