ビット演算子は整数型の個々のビットを操作します:
& — ビットごとのAND| — ビットごとのOR^ — ビットごとの排他的OR~ — ビットごとのNOT<< — 左シフト>> — 右シフト特性:
int、unsigned intなど)でのみ動作します。signed)は右シフト(>>)時に算術シフトまたは論理シフトを生成することがあります — これはコンパイラによって異なります。unsigned)を選択することが多いです。例:
unsigned int flags = 0; flags |= 0x1; // 0番ビットをセット flags &= ~0x2; // 1番ビットをリセット if ((flags & 0x4) != 0) { /* ... */ } // 2番ビットをチェック
signed intとunsigned intタイプの右シフト(>>)の違いは何ですか?
よくある誤った答え: 右シフトは常に左側にゼロを挿入すると考えられています。
正しい答え:
unsigned int タイプの右シフト(>>)は常にゼロを挿入します。signed int では符号(負の数の場合は1)またはゼロが挿入されます — これはコンパイラの実装(アーキテクチャおよびC標準の規則)に依存します。
例:
signed int a = -8; unsigned int b = (unsigned int)a; printf("%d ", a >> 1); printf("%u ", b >> 1);
最初の場合、結果はコンパイラによって異なります。2番目の場合は常にゼロでの論理シフトになります。
物語
プロトコル処理のコードでは、信号フラグが char 型に保存されていました。プログラマーは8ビットシフト(flag << 8)を適用し、オーバーフローと型昇格の規則によりすべてのデータが失われました — 結果は常にゼロになりました。
物語
ネットワークプロトコルからのデータ読み込み(ビッグエンディアン)。バイトを結合するためのビット演算の使用は unsigned へのキャストを伴わず、これが構造体のフィールドを読み取るときに予期しない負の値を生むことがありました。
物語
~(ビットごとのNOT)を使用して int 型の値のビットをリセットする(例:~0x80)と、0x7Fと見なされましたが、実際には負の数 -129 が得られ、その後の計算や論理チェックでエラーを引き起こしました。