11

数値の異なるバイナリ表現 (たとえば、ビッグ/リトル エンディアンを取る) と同様に、このクロスプラットフォームは次のとおりです。

// NOTE: FIXED-SIZE unsigned integral type
some_unsigned_type variable = some_number;

// set n-th bit, starting from 1,
// right-to-left (least significant-to most significant)
variable |= ( 1 << ( n - 1 ) );

// clear the same bit:    
variable &= ~( 1 << ( n - 1 ) );

言い換えれば、コンパイラは常に固定サイズの符号なし数値の異なるバイナリ表現を処理しますか、それともプラットフォーム固有ですか?

が符号付き整数variable型 (たとえばint) で、その値が

  • ゼロ
  • ポジティブ
  • ネガティブ?

規格はこれについて何と言っていますか?

PSそして、はい、私は両方に興味があります-CそしてC++、私はこれを知っているので、それらが異なる言語であると私に言わないでください:)

必要に応じて実際の例を貼り付けることができますが、投稿が長くなりすぎます

4

3 に答える 3

6

some_unsigned_typeが固定幅タイプでない限り、これは最初のプラットフォーム固有です。あるプラットフォームでは、値自体によって決して繰り返されない情報をシフトアウトしている可能性がありますが、別のプラットフォームではそうでない可能性があります。例:

16 bit 'int':

      1000 0000  0000 0000
<<1 = 0000 0000  0000 0000
>>1 = 0000 0000  0000 0000

32 bit 'int':

      0000 0000  0000 0000   1000 0000  0000 0000
<<1 = 0000 0000  0000 0001   0000 0000  0000 0000
>>1 = 0000 0000  0000 0000   1000 0000  0000 0000

5.8 Shift OperatorsC++標準では、次のようにも述べています。

右オペランドが負の場合、またはプロモートされた左オペランドのビット長以上の場合、動作は未定義です。

したがって、整数を実際よりも多くのビットだけシフトすると、未定義の動作に入ります。たとえば、short値を 17 ビット左シフトすると、すべてのマシンではなく一部のマシンで UB が得られる場合があります。

C11 は、6.5.7 Bitwise shift operators他のこととは別に、次のように述べています。

の結果E1 >> E2E1右シフトされたE2ビット位置です。E1が unsigned 型の場合、またはsignedE1型で非負の値の場合、結果の値は の商の整数部分ですE1 / 2E2符号付きの型と負の値を持つ場合E1、結果の値は実装定義です。

そのため、符号付き数値シフトは移植性がありません。

したがって、一般的な整数の一般的な答えは次のとおり です。

整数のビット操作は移植性がありません。

于 2012-10-04T15:16:19.127 に答える
5

免責事項:固定幅の整数型について話していると暗黙のうちに想定しています。それ以外の場合のビットシフトは非常に危険です...

標準: n3337 C++11

シフトの定義は、符号なしの型または符号付きの型 (*) の正の値の数学的であるため、基になるハードウェア表現の影響を受けません。

5.8 シフト演算子 [expr.shift]

2の値E1 << E2E1左シフトされたE2ビット位置です。空いたビットはゼロで埋められます。E1が unsigned 型の場合、結果の値はE1 × 2E2であり、結果の型で表現可能な最大値より 1 を法として減じられます。それ以外の場合E1、符号付きの型と負でない値を持ちE1×2E2、結果の型で表現できる場合、それが結果の値です。それ以外の場合、動作は未定義です。

3の値E1 >> E2E1右シフトされたE2ビット位置です。E1が unsigned 型の場合、またはsignedE1型で負でない値の場合、結果の値は の商の整数部分ですE1/2E2。符号付きの型と負の値を持つ場合E1、結果の値は実装定義です。

同じ理由で、私は bitwise と考えますが、and大丈夫orですnegate。それらは数学的に定義されています。

5.3.1 単項演算子 [expr.unary.op]

10のオペランドは、˜整数型または範囲指定なしの列挙型でなければなりません。結果はそのオペランドの 1 の補数です。

5.11 ビット AND 演算子 [expr.bit.and]

1通常の算術変換が実行されます。結果は、オペランドのビットごとの AND 関数です。演算子は、整数またはスコープなしの列挙型オペランドにのみ適用されます。

5.13 ビット単位の包含 OR 演算子 [expr.or]

1通常の算術変換が実行されます。結果は、そのオペランドのビットごとの包括的 OR 関数です。演算子は、整数またはスコープなしの列挙型オペランドにのみ適用されます。

ただし、後者の 2 つについてはあまり確信が持てないことを認めます。ビットごとの XX functionの定義を見つけることができませんでした。

(*) それを指摘してくれた phresnel に感謝します。

于 2012-10-04T15:35:52.523 に答える
1

負の(または符号付きの)数値をシフトする場合は、実装固有です(ほとんどの実装では同じ U2 のものです)。変数のビット数を超えない値で符号なし数値をシフトする場合、ほとんどの用途で移植可能です。

于 2012-10-04T16:34:47.987 に答える