web-dev-qa-db-ja.com

ビットシフトはエンディアンに依存しますか?

番号'numb'=1025 [00000000 00000000 00000100 00000001]が表されているとします:

リトルエンディアンマシンの場合:

00000001 00000100 00000000 00000000

ビッグエンディアンのマシン:

00000000 00000000 00000100 00000001

ここで、10ビットに左シフトを適用すると(つまり、numb << = 10)、次のようになります。

[A]リトルエンディアンマシンの場合:

GDBで気づいたように、リトルエンディアンは左シフトを3ステップで実行します。[処理のみをよりよく理解するために '3'ステップを示しました]

  1. いいえを扱いますビッグエンディアン条約で:

    00000000        00000000        00000100    00000001
    
  2. 左シフトを適用:

    00000000        00010000        00000100        00000000
    
  3. 結果を再びリトルエンディアンで表します。

    00000000        00000100        00010000        00000000 
    

[B]。ビッグエンディアンのマシン:

00000000        00010000        00000100        00000000

私の質問は:

リトルエンディアンコンベンションに直接左シフトを適用すると、次のようになります。

numb

00000001 00000100 00000000 00000000

numb << 10

00010000 00000000 00000000 00000000

しかし、実際には次のことができます。

00000000        00000100        00010000        00000000 

2番目の結果のみを達成するために、上記の3つの仮想ステップを示しました。

上記の2つの結果が異なる理由を説明してください。numb << 10の実際の結果は、予想される結果とは異なります。

141
Sandeep Singh

エンディアンネスは、値がメモリに格納される方法です。エンディアンに関係なく、プロセッサにロードされると、ビットシフト命令はプロセッサのレジスタの値で動作します。したがって、メモリからプロセッサへのロードはビッグエンディアンへの変換に相当し、次にシフト操作が行われ、新しい値がメモリに格納されます。ここで、リトルエンディアンのバイト順が再び有効になります。

@jwwのおかげで更新:PowerPCでは、ベクトルのシフトと回転はエンディアンに依存します。ベクトルレジスタに値を入れてシフトすることができます リトルエンディアンとビッグエンディアンで異なる結果を生成します

181
Carl

いいえ、ビットシフトは、Cの他の部分と同様に、表現ではなくvaluesで定義されます。左シフト1は2倍、右シフトは除算です。 (ビット単位演算を使用するときはいつものように、符号性に注意してください。すべては、符号なし整数型に対して最も明確に定義されています。)

53
Kerrek SB

いずれのシフト命令が最初に上位ビットをシフトアウトする場合でも、左シフトと見なされます。どのシフト命令が最初に下位ビットをシフトアウトする場合でも、右シフトと見なされます。その意味では、>>および<< for unsigned番号は、エンディアンに依存しません。

4
Davislor

コンピューターは私たちのやり方で数字を書きません。値は単純にシフトします。バイト単位で見ることにこだわるなら(コンピューターのやり方ではありませんが)、リトルエンディアンのマシンでは、最初のバイトが左にシフトし、余分なビットが2番目のバイトに入ります。等々。

(ちなみに、バイトを水平方向ではなく垂直方向に書き込み、上位に上位アドレスを指定すると、リトルエンディアンがより意味を持ちます。これは、メモリマップダイアグラムの一般的な描画方法です。)

3
Raymond Chen