C语言 位移是否取决于字节序?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7184789/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 09:28:39  来源:igfitidea点击:

Does bit-shift depend on endianness?

cendianness

提问by Sandeep Singh

Suppose I have the number 'numb'=1025 [00000000 00000000 00000100 00000001]represented:

假设我有'numb'=1025 [00000000 00000000 00000100 00000001]代表的数字:

On Little-Endian Machine:

在小端机器上:

00000001 00000100 00000000 00000000

On Big-Endian Machine:

在大端机器上:

00000000 00000000 00000100 00000001

Now, if I apply Left Shift on 10 bits (i.e.: numb <<= 10), I should have:

现在,如果我在 10 位上应用左移(即:numb <<= 10),我应该有:

[A] On Little-Endian Machine:

[A] 在小端机器上:

As I noticed in GDB, Little Endian does the Left Shift in 3 steps: [I have shown '3' Steps to better understand the processing only]

正如我在 GDB 中注意到的,Little Endian 分 3 个步骤进行左移:[我已经展示了“3”步以更好地理解处理过程]

  1. Treat the no. in Big-Endian Convention:

    00000000        00000000        00000100    00000001
    
  2. Apply Left-Shift:

    00000000        00010000        00000100        00000000
    
  3. Represent the Result again in Little-Endian:

    00000000        00000100        00010000        00000000 
    
  1. 对待没有。在 Big-Endian 公约中:

    00000000        00000000        00000100    00000001
    
  2. 应用左移:

    00000000        00010000        00000100        00000000
    
  3. 在 Little-Endian 中再次表示结果:

    00000000        00000100        00010000        00000000 
    

[B]. On Big-Endian Machine:

[乙]。在大端机器上:

00000000        00010000        00000100        00000000


My Question is:

我的问题是:

If I directly apply a Left Shift on the Little Endian Convention, it should give:

如果我直接在 Little Endian 约定上应用左移,它应该给出:

numb:

numb

00000001 00000100 00000000 00000000

numb << 10:

numb << 10

00010000 00000000 00000000 00000000

But actually, it gives:

但实际上,它给出了:

00000000        00000100        00010000        00000000 

To achieve the second result only, I have shown three hypothetical steps above.

为了仅实现第二个结果,我在上面展示了三个假设步骤。

Please explain me why the above two results are different: The actual outcome of numb << 10is different than the expected outcome.

请解释为什么上述两个结果不同: 的实际结果numb << 10与预期结果不同。

回答by Carl

Endianness is the way values are stored in memory. When loaded into the processor, regardless of endianness, the bit shift instruction is operating on the value in the processor's register. Therefore, loading from memory to processor is the equivalent of converting to big endian, the shifting operation comes next and then the new value is stored back in memory, which is where the little endian byte order comes into effect again.

字节序是值存储在内存中的方式。当加载到处理器中时,无论字节序如何,位移指令都会对处理器寄存器中的值进行操作。因此,从内存加载到处理器相当于转换为大端,接下来进行移位操作,然后将新值存储回内存,这就是小端字节顺序再次生效的地方。

Update, thanks to @jww: On PowerPC the vector shifts and rotates are endian sensitive. You can have a value in a vector register and a shift will produce different results on little-endian and big-endian.

更新,感谢@jww:在 PowerPC 上,矢量移位和旋转对字节序敏感。您可以在向量寄存器中有一个值,并且移位将在 little-endian 和 big-endian 上产生不同的结果

回答by Kerrek SB

No, bitshift, like any other part of C, is defined in terms of values, not representations. Left-shift by 1 is mutliplication by 2, right-shift is division. (As always when using bitwise operations, beware of signedness. Everything is most well-defined for unsigned integral types.)

不,像 C 的任何其他部分一样,bitshift 是根据而不是表示来定义的。左移 1 是乘以 2,右移是除法。(在使用按位运算时,请注意有符号性。对于无符号整数类型,一切都是最明确定义的。)

回答by Davislor

Whichever shift instruction shifts out the higher-order bits first is considered the left shift. Whichever shift instruction shifts out the lower-order bits first is considered the right shift. In that sense, the behavior of >>and <<for unsignednumbers will not depend on endianness.

无论哪个移位指令先移出高位,都被认为是左移。无论哪个移位指令先移出低位,都被认为是右移。在这个意义上说,行为>><<unsigned数将不依赖于字节序。

回答by Raymond Chen

Computers don't write numbers down the way we do. The value simply shifts. If you insist on looking at it byte-by-byte (even though that's not how the computer does it), you could say that on a little-endian machine, the first byte shifts left, the excess bits go into the second byte, and so on.

计算机不像我们那样写数字。价值只是改变。如果您坚持逐字节查看它(即使计算机不是这样做的),您可以说在小端机器上,第一个字节左移,多余的位进入第二个字节,等等。

(By the way, little-endian makes more sense if you write the bytes vertically rather than horizontally, with higher addresses on top. Which happens to be how memory map diagrams are commonly drawn.)

(顺便说一句,如果您垂直而不是水平地写入字节,并且在顶部具有更高的地址,那么 little-endian 更有意义。这恰好是通常绘制内存映射图的方式。)

回答by Rick

Though the accepted answer points out that endianess is a concept from the memory view. But I don't think that answer the question directly.

尽管已接受的答案指出字节序是内存视图中的一个概念。但我认为这并不能直接回答问题。

Some answers tell me that bitwise operations don't depend on endianess, and the processor may represent the bytes in any other way. Anyway, it's talking about that endianess gets abstracted.

一些答案告诉我,按位运算不依赖于字节序,并且处理器可能以任何其他方式表示字节。无论如何,它谈论的是字节序被抽象化了。

But when we do some bitwise calculations on the paper for example, don't need to state the endianess in the first place? Most times we choose an endianess implicitly.

但是,例如,当我们在论文上进行一些按位计算时,不需要首先说明字节序吗?大多数时候我们会隐含地选择一个字节序。

For example, assume we have a line of code like this

例如,假设我们有这样一行代码

0x1F & 0xEF

0x1F & 0xEF

How would you calculate the result by hand, on a paper?

您将如何在纸上手工计算结果?

  MSB   0001 1111  LSB
        1110 1111
result: 0000 1111

So here we use a Big Endian format to do the calculation. You can also use Little Endian to calculate and get the same result.

所以这里我们使用 Big Endian 格式进行计算。您也可以使用 Little Endian 来计算并得到相同的结果。

Btw, when we write numbers in code, I think it's like a Big Endian format. 123456or 0x1F, most significant numbers starts from the left.

顺便说一句,当我们在代码中编写数字时,我认为它就像一个 Big Endian 格式。123456或者0x1F,最重要的数字从左边开始。

Again, as soon as we write some a binary format of a value on the paper, I think we've already chosen an Endianess and we are viewing the value as we see it from the memory.

同样,一旦我们在纸上写了一些二进制格式的值,我想我们已经选择了一个 Endianess,我们正在查看我们从内存中看到的值。

So back to the question, an shift operation <<should be thought as shifting from LSB(least significant byte) to MSB(most significant byte).

所以回到问题,移位操作<<应该被认为是从 LSB(最低有效字节)到 MSB(最高有效字节)

Then as for the example in the question:

那么对于问题中的例子:

numb=1025

numb=1025

Little Endian

小端

LSB 00000001 00000100 00000000 00000000 MSB

LSB 00000001 00000100 00000000 00000000 MSB

So << 10would be 10bitshifting from LSB to MSB.

所以<< 1010bit转向从LSB到MSB。



Comparison and << 10operations for Little Endian format step by step:

<< 10Little Endian 格式的分步比较和操作:

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

Wow! I get the expected result as the OP described!

哇!我得到了 OP 描述的预期结果!

The problems that the OP didn't get the expected result are that:

OP没有得到预期结果的问题是:

  1. It seems that he didn't shift from LSB to MSB.

  2. When shifting bits in Little Endian format, you should realize(thank god I realize it) that:

  1. 似乎他没有从 LSB 转变为 MSB。

  2. 当以 Little Endian 格式移动位时,您应该意识到(感谢上帝我意识到了):

LSB 10000000 00000000 MSB << 1is
LSB 00000000 00000001 MSB, notLSB 01000000 00000000 MSB

LSB 10000000 00000000 MSB << 1
LSB 00000000 00000001 MSB不是LSB 01000000 00000000 MSB

Because for each individual 8bits, we are actually writing it in a MSB 00000000 LSBBig Endian format.

因为对于每个人8bits,我们实际上是以MSB 00000000 LSB大端格式编写的。

So it's like

所以就像

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB

LSB[ (MSB 10000000 LSB) (MSB 00000000 LSB) ]MSB



To sum up:

总结:

  1. Though bitwise operations is said to be abstracted away blablablabla..., when we calculate bitwise operations by hand, we still need to know what endianess we are using as we write down the binary format on the paper. Also we need to make sure all the operators use the same endianess.

  2. The OP didn't get the expected result is because he did the shifting wrong.

  1. 虽然据说按位运算被抽象掉了 blablablabla...,但当我们手动计算按位运算时,我们仍然需要知道我们使用的是什么字节序,因为我们在纸上写下二进制格式。我们还需要确保所有操作符都使用相同的字节序。

  2. OP没有得到预期的结果是因为他做错了转移。