C 位偏移是否取决于端度?
假设我将数字C 位偏移是否取决于端度?,c,endianness,C,Endianness,假设我将数字'numb'=1025[0000000000000000000000001000000000001]表示为: 在Little Endian机器上: 00000001 00000100 00000000 00000000 00000000 00000000 00000100 00000001 00000000 00010000 00000100 00000000 在Big-Endian机器上: 00000001 00000100 0000
'numb'=1025[0000000000000000000000001000000000001]
表示为:
在Little Endian机器上:
00000001 00000100 00000000 00000000
00000000 00000000 00000100 00000001
00000000 00010000 00000100 00000000
在Big-Endian机器上:
00000001 00000100 00000000 00000000
00000000 00000000 00000100 00000001
00000000 00010000 00000100 00000000
现在,如果我对10位应用左移位(即:numbNo,位移位与C的任何其他部分一样,都是用值定义的,而不是用表示。左移位1表示多应用2,右移位表示除法。(和往常一样,在使用位运算时,要注意符号性。对于无符号整数类型,一切都定义得很好。)计算机不像我们那样写数字。值只是移位。如果你坚持逐字节查看它(即使计算机不是这样做的),你可以说在一台小型endian机器上,第一个字节向左移位,多余的位进入第二个字节,依此类推
(顺便说一句,如果您垂直写入字节而不是水平写入字节,并且在顶部有更高的地址,那么little endian更有意义。内存映射图通常就是这样绘制的。)Endianness是存储在内存中的值的方式。当加载到处理器中时,不管Endianness如何,位移位指令都对处理器寄存器中的值进行操作。因此,从内存加载到处理器相当于转换为big-endian,接下来是移位操作,然后是新值返回内存,在内存中,小端字节顺序再次生效
更新,感谢@jww:在PowerPC上,向量移位和旋转是endian敏感的。你可以在向量寄存器中有一个值和一个移位。任何移位指令首先移出高阶位都被视为左移位。任何移位指令首先移出低阶位都被视为右移位。I从这个意义上讲,
>
和的行为虽然公认的答案指出,从记忆的角度来看,持久性是一个概念,但我认为这并不能直接回答这个问题
一些答案告诉我,按位运算不依赖于endianess,处理器可以用任何其他方式表示字节。总之,它说的是endianess被抽象了
但是当我们在纸上做一些按位计算时,首先不需要声明endianess吗?大多数情况下,我们隐式地选择endianess
例如,假设我们有一行这样的代码
0x1F&0xEF
你如何在纸上手工计算结果
MSB 0001 1111 LSB
1110 1111
result: 0000 1111
所以这里我们使用一个大端元格式来进行计算。你也可以使用小端元来计算,得到相同的结果
顺便说一句,当我们用代码写数字时,我认为这就像是一种大端格式。123456
或0x1F
,最重要的数字从左边开始
再一次,当我们在纸上写一些二进制格式的值时,我想我们已经选择了一个Endianess,我们正在查看从内存中看到的值
回到问题上来,移位运算对于整数运算基本上是正确的,但C确实提供了大量依赖于表示的行为。@Edmund:Hm…最明显的是,没有指定有符号性的实现,因此导致了按位运算的行为(如右移)模和除的函数是在负整数上定义的。你还想知道什么是实现定义的吗?@KerrekSB不幸的是,它们不是在负整数上定义的。它们在C89中未指定,在C99+中未定义,这是一个非常糟糕的主意。@PaoloBonzini:是的,很好。事实上这是正确的更好的是,因为它强调了移位操作是根据值定义的,当结果不可表示时可能是未定义的,而对底层表示的推测也没有帮助。@KerrekSB:问题是每个人实际上都需要左移位来表示为值和表示依情况而定。使用无符号整数可能会导致其他问题,例如x&=-1u谢谢你的解释。你能推荐一些参考资料,让我更好地理解这些复杂的问题吗。理解endianness的最好方法是在嵌入式级别的不同体系结构上真正使用它。如何我可以把你提到这两篇文章:所以我的代码不管Endiad如何都能工作!这太好了!我一直担心我必须把我的代码破解到地狱里去!“MARCUJ:不一定。例如,如果你从一个32位整数的文件中读取4字节,你需要考虑你正在读取的数据的迂回性。结合接收数据的系统的端度,以便正确解释数据。在PowerPC上,向量移位和旋转是端度敏感的。向量寄存器中可以有一个值,移位将在小端和大端产生不同的结果。
00010000 00000000 00000000 00000000
00000000 00000100 00010000 00000000
MSB 0001 1111 LSB
1110 1111
result: 0000 1111
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!)