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!)