>>
符号付き整数の動作は実装に依存する可能性があることを私は知っています(具体的には、左のオペランドが負の場合)。
~
他の>>
人&
はどうですか:^
、、、、、|
?それらのオペランドが組み込み型(、、、、)の符号付き整数であるshort
場合int
、それらの型が符号なしであるかのように、結果は(ビットの内容long
に関してlong long
)同じであることが保証されますか?
>>
符号付き整数の動作は実装に依存する可能性があることを私は知っています(具体的には、左のオペランドが負の場合)。
~
他の>>
人&
はどうですか:^
、、、、、|
?それらのオペランドが組み込み型(、、、、)の符号付き整数であるshort
場合int
、それらの型が符号なしであるかのように、結果は(ビットの内容long
に関してlong long
)同じであることが保証されますか?
負のオペランドの場合、<<
は未定義の動作をし、結果>>
は実装で定義されます(通常は「算術」右シフトとして)。<<
概念的に>>
はビット演算子ではありません。これらは、明確に定義されているオペランドの2の適切な累乗による乗算または除算と同等の算術演算子です。
本物のビット演算子、、、、^
およびは~
、オペランドの(プロモートされている可能性がある)タイプの値のビット表現を操作します。それらの結果は、符号付き表現(2の補数、1の補数、または符号の大きさ)の可能な選択肢ごとに明確に定義されていますが、後者の2つのケースでは、実装が「負のゼロ」を処理する場合、結果がトラップ表現になる可能性があります。トラップとしての表現。個人的には、ほとんどの場合、ビット単位の演算子を使用して符号なし式を使用するため、結果は表現ではなく値に関して100%明確に定義されます。|
&
最後に、書かれているこの回答はCにのみ適用される可能性があることに注意してください。CとC ++は非常に異なる言語であり、C ++についてはよくわかりませんが、これらの領域の一部でCとは異なる可能性があることを理解しています...
<<
には未定義の動作があります。>>
負の値を右シフトすると、実装定義の結果が得られます。&
、|
および演算子の結果は^
、値のビット単位の表現で定義されます。Cでの負の数の表現には、2の補数、1の補数、および符号の大きさの3つの可能性があります。実装で使用されるメソッドは、これらの演算子が負の値で使用される場合の数値結果を決定します。符号ビット1とすべての値ビットがゼロ(2の補数と符号の大きさの場合)、または符号ビットとすべての値のビット1(1の補数の場合)の値は、トラップ表現として明示的に許可されていることに注意してください。このような値を生成するこれらの演算子への引数を使用する場合、動作は定義されていません。
ビットの内容は同じですが、結果の値は実装に依存します。
ビット単位の演算を使用する場合、値が符号付きまたは符号なしとして表示されるべきではありません。これは、別のレベルで機能しているためです。
符号なし型を使用すると、この問題の一部を回避できます。
C89標準は、ビット位置に基づいて左シフト符号付き数値の動作を定義しました。符号付き型と符号なし型のどちらにもパディングビットがない場合、符号なし型に必要な動作と、正の符号付き型が符号なし型と同じ表現を共有するという要件は、符号ビットが最上位ビットのすぐ左にあることを意味します。 。
これは、C89では、-1 << 1は、パディングビットを持たない2の補数の実装では-2になり、1の補数の実装ではパディングビットを持たない-3になります。パディングビットのない符号の大きさの実装がある場合、-1<<1はそれらの2に等しくなります。
C99標準は、負の値の左シフトを未定義動作に変更しましたが、その理由についての手がかりは何もありません(または変更についても言及していません)。C89で必要とされる動作は、一部の1の補数の実装では理想的とは言えない可能性があるため、これらの実装がより適切なものを自由に選択できるようにすることは理にかなっています。標準の作成者が、高品質の2の補数の実装が、C89で義務付けられているのと同じ動作を提供し続けることを意図していなかったことを示唆する証拠は見ていませんが、残念ながら実際にはそうは言っていません。