HOWTO · C

C でのビット演算

この記事では、C でのビット単位の操作の使用方法を示し、これらのビット単位の操作を使用するためのよく誤解されている簡略表記の表記法を示します。

この記事では、C のビット演算 (および演算子) について説明します。これらの概念は C++ にも拡張されています。

これらの演算子に加えて、この記事では、よく誤解されている演算子代入の簡略表記 (+= 演算子代入など) について説明します。 これについては、ビット演算子のコンテキストで説明します。

この記事では、表記法とそれぞれの出力の両方を示すこれらの各演算子の例を示します。 また、C でサポートされていない省略表記についても説明します。

最後に、コンパイラがトークンを生成するプログラムのコンパイルの段階である字句解析について簡単に説明します。 これらは、キーワード、識別子、定数、文字列リテラルなど、コードの最小部分です。

ビット演算子 & および &= 演算子

&ビットごとの and 演算子です。 次のように使用されます。

int test = 0x6A;
test = test & 0x50;

上記のコードは、0x6A0x50 の間でビットごとの and 比較を実行し、結果を test 変数に保存します。 ビットごとの and 演算は、両方の引数の各ビットを比較します。

両方のオペランドのビットが 1 の場合、各ビットの結果は 1 になり、それ以外の場合は 0 になります。

0x6A のバイナリは 1101010 で、0x50 のバイナリは 1010000 です。 したがって、and 演算の結果は 1000000 になります。

ここで、簡略記法について説明します。 上記のコードは、次のように簡単に記述できます。

int test2 = 0x6A;
test2 &= 0x50;

一般に、x &= 5x = x & 5 と同等です。 ただし、これは他の操作にも拡張できます。 最も一般的なのは、+=-=*=/= です。

この簡略表記のより一般的な例は、>>=<<=|=&=^= などのビット演算です。

ビット単位 | および |= 演算子

|ビット単位の包括的 or 演算子です。

int test = 0x6A;
test = test | 0x50;

これを簡略化すると、次のようになります。

int test = 0x6A;
test |= 0x50;

test の結果の値は 1111010 です。

ビット単位の包括的な or 演算は、両方の引数の各ビットを比較します。 オペランドのいずれかのビットが 1 の場合、各ビットの結果は 1 になり、両方のオペランドが 0 の場合のみ、結果は 0 になります。

ビット単位の ^ および ^= 演算子

^ビットごとの排他的 or 演算子です。

int test = 0x6A;
test = test ^ 0x50;

これを簡略化すると、次のようになります。

int test = 0x6A;
test ^= 0x50;

test の結果の値は、0111010 です。

ビットごとの排他的な or 演算は、両方の引数の各ビットを比較します。 2つのビットの値が異なる場合、結果の各ビットのビット値は 1 です。 両方のビットが同じ値の場合は 0 です。

ビットシフト (>>) および (<<) 演算子

シフト演算子には 2つのオペランドがあります。

シフトはオペランドの左に適用されます。 また、シフトが適用されるビット数は、右側のオペランドによって決まります。

シフトには、左シフト << と右シフト >> の 2 種類があります。 一般的には次のように使用されます。

詳細が不明な場合は、シフト演算子の結果の詳細について、この リンクされたドキュメント を参照してください。

int test5 = 0xFF;
test5 = test5 << 2;

この例では、test5 に格納されているビットは、(オペレーターの指示に従って) 2 ビット左にシフトされます。

Before shift : 0011111111 After shift : 1111111100

同様に、右シフトの場合:

int test5 = 0xFF;
test5 = test5 >> 2;

この例では、test5 に格納されたビットが 2 ビット右シフトされます。

Before shift : 11111111 After shift : 00111111

右シフトと左シフトの簡略表記は、上記のものと似ています。

省略形の右シフト表記:

int test5 = 0xFF;
test5 >>= 2;

省略形の左シフト表記:

int test5 = 0xFF;
test5 <<= 2;

算術略記 (複合代入ステートメント)

このセクションでは、算術演算の省略形について簡単に説明します。 変数宣言の後の次の 2つのステートメントは同等です。

追加の場合:

int addTest = 5;

addTest += 5;

addTest = addTest + 5;

乗算の場合:

int multTest = 5;

multTest *= 5;

multTest = multTest * 5;

除算の場合:

int divTest = 5;

divTest /= 5;

divTest = divTest / 5;

減算の場合:

int subTest = 5;

subTest -= 5;

subTest = subTest - 5;

モジュロ/剰余 (%) の場合:

int remTest = 5;

remTest %= 5;

remTest = remTest % 5;

字句解析とできないこと

字句解析は、各オペランドと演算子がトークンに分離される段階です。 たとえば、ステートメント x + 2 の場合、x は変数であり、アナライザーは x2 をオペランドとして、+ を演算子として分離します。

簡略表記の場合、|= などの演算子は、それらを識別するのに十分なトークン コードとともに格納されます。 ショートハンドが機能しない場合、それらは (単純に) C 語彙アナライザー用に定義されていません。 それらが字句アナライザーを通過しても、構文アナライザーはそれらを拒否します。

これが、>>>>||=&&= などの短縮形が機能しない理由です。 おそらく、有効な演算子として受け入れられるプログラミング言語が存在するでしょう。