ビット演算を理解してフラグを使いこなす - C#

フラグの取得、設定(追加)、解除を行います。

理解しやすくするために0~9の数値に該当するビットを対象に、そして比較しやすいように桁数を4桁に統一し、話を進めます。

2進数対応表
10進数2進数
00000
10001
20010
30011
40100
50101
60110
70111
81000
91001
ビット演算子
演算子説明
&論理積
|論理和
^排他的論理和
~反転


ビット演算表

ビット&|^
000 00
01011
10011
11110



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

Recent Posts