假设我有数字'numb'=1025 [00000000 00000000 00000100 00000001]
:
在Little-Endian机器上:
00000001 00000100 00000000 00000000
在Big-Endian机器上:
00000000 00000000 00000100 00000001
现在,如果我在10位上应用左移(即:numb<< = 10),我应该:
[A]在Little-Endian机器上:
正如我在GDB中所注意到的,Little Endian通过3个步骤执行左移:[我已经显示'3'步骤以更好地理解处理]
对待不。在Big-Endian公约中:
00000000 00000000 00000100 00000001
应用左移:
00000000 00010000 00000100 00000000
再次在Little-Endian中表示结果:
00000000 00000100 00010000 00000000
[B]。在Big-Endian机器上:
00000000 00010000 00000100 00000000
我的问题是:
如果我直接在Little Endian上应用左移 公约,应该给出:
numb
:
00000001 00000100 00000000 00000000
numb << 10
:
00010000 00000000 00000000 00000000
但实际上,它给出了:
00000000 00000100 00010000 00000000
为了达到第二个结果,我在上面展示了三个假设步骤。
请解释为什么以上两个结果不同:numb << 10
的实际结果与预期结果不同。
答案 0 :(得分:177)
Endianness是值存储在内存中的方式。当加载到处理器中时,无论字节顺序如何,位移指令都在处理器寄存器中的值上运行。因此,从内存加载到处理器相当于转换为大端,接下来是移位操作,然后将新值存储回内存,这是小端字节顺序再次生效的地方。
更新,感谢@jww:在PowerPC上,向量移位和旋转是字节序敏感的。您可以在向量寄存器中使用值will produce different results on little-endian and big-endian。
答案 1 :(得分:51)
不,像C的任何其他部分一样,bitshift是根据值而不是表示来定义的。左移1是多重乘以2,右移是除法。 (与使用按位运算时一样,请注意有符号性。对于无符号整数类型,一切都是最明确定义的。)
答案 2 :(得分:4)
无论哪个移位指令移出,高阶位首先被认为是左移位。无论哪个移位指令首先移出低位,都被认为是右移位。从这个意义上说,>>
和<<
对unsigned
数字的行为不会取决于字节顺序。
答案 3 :(得分:3)
计算机不会像我们一样写下数字。价值只是转移。如果你坚持逐字节查看它(即使这不是计算机的工作方式),你可以说在小端机器上,第一个字节向左移,多余的位进入第二个字节,等等。
(顺便说一句,如果你把字节垂直而不是水平地写,那么little-endian更有意义,顶部有更高的地址。这通常是如何绘制存储器映射图。)
答案 4 :(得分:0)
尽管接受的答案指出,记忆力是记忆力的一个概念。但是我不认为直接回答这个问题。
一些答案告诉我按位运算不依赖于字节序,处理器可以用任何其他方式表示字节。无论如何,这是在说抽象性。
但是,例如当我们在纸上进行按位计算时,是否无需首先说明字节序?大多数情况下,我们会隐式选择一个字节序。
例如,假设我们有一行这样的代码
0x1F & 0xEF
您将如何在纸上手工计算结果?
MSB 0001 1111 LSB
1110 1111
result: 0000 1111
因此,这里我们使用Big Endian格式进行计算。您还可以使用Little Endian计算并获得相同的结果。
顺便说一句,当我们用代码写数字时,我认为这就像是Big Endian格式。 123456
或0x1F
,最重要的数字从左开始。
同样,当我们在纸上写一个值的二进制格式后,我认为我们已经选择了Endianess,并且正在从内存中查看该值。
所以回到问题上,移位操作<<
应该被认为是从LSB(最低有效字节)到MSB(最高有效字节)的转移。
然后以问题中的示例为例:
numb=1025
小尾数
LSB 00000001 00000100 00000000 00000000 MSB
因此<< 10
将10bit
从LSB转换为MSB。
Little Endian格式的比较和<< 10
操作:
MSB LSB
00000000 00000000 00000100 00000001 numb(1025)
00000000 00010000 00000100 00000000 << 10
LSB MSB
00000000 00000100 00010000 00000000 numb(1025) << 10, and put in a Little Endian Format
LSB MSB
00000001 00000100 00000000 00000000 numb(1205) in Little Endian format
00000010 00001000 00000000 00000000 << 1
00000100 00010000 00000000 00000000 << 2
00001000 00100000 00000000 00000000 << 3
00010000 01000000 00000000 00000000 << 4
00100000 10000000 00000000 00000000 << 5
01000000 00000000 00000001 00000000 << 6
10000000 00000000 00000010 00000000 << 7
00000000 00000001 00000100 00000000 << 8
00000000 00000010 00001000 00000000 << 9
00000000 00000100 00010000 00000000 << 10 (check this final result!)
哇!如操作说明所述,我得到了预期的结果!
OP未能获得预期结果的问题是:
似乎他没有从LSB转到MSB。
当以Little Endian格式转换位时,您应该意识到(感谢上帝,我意识到了):
LSB 10000000 00000000 MSB << 1
是
LSB 00000000 00000001 MSB
,不
LSB 01000000 00000000 MSB
由于每个8bits
,我们实际上都是以MSB 00000000 LSB
Big Endian格式编写的。
所以就像
LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB
总结:
尽管据说按位运算已被抽象出来了……但是,当我们手动计算按位运算时,当我们在纸上写下二进制格式时,我们仍然需要知道我们正在使用什么字节序。另外,我们需要确保所有运算符都使用相同的字节序。
OP未能获得预期的结果是因为他犯了错。