Programming組み込みCエンジニア

C言語におけるビット演算子(&, |, ^, ~, <<, >>)はどのように機能しますか?異なる長さと符号の型を扱う際の特性は何ですか?開発者が利用時に犯す一般的なミスは何ですか?

Hintsage AIアシスタントで面接を突破

答え。

ビット演算子は整数型の個々のビットを操作します:

  • & — ビットごとのAND
  • | — ビットごとのOR
  • ^ — ビットごとの排他的OR
  • ~ — ビットごとのNOT
  • << — 左シフト
  • >> — 右シフト

特性:

  • 演算子は整数型(intunsigned intなど)でのみ動作します。
  • 符号付き数(signed)は右シフト(>>)時に算術シフトまたは論理シフトを生成することがあります — これはコンパイラによって異なります。
  • 変数のビット数を超えるシフトでは未定義の動作が発生します。
  • 信頼性の高い動作を確保するために、符号なし型(unsigned)を選択することが多いです。

例:

unsigned int flags = 0; flags |= 0x1; // 0番ビットをセット flags &= ~0x2; // 1番ビットをリセット if ((flags & 0x4) != 0) { /* ... */ } // 2番ビットをチェック

トリビアな質問。

signed intunsigned 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 が得られ、その後の計算や論理チェックでエラーを引き起こしました。