小端大端的混淆

8 c bitwise-operators

我对小端/大端有些困惑.似乎我很简单.一些反馈意见.例如,假设我们有两个函数可以检索
32位值的最小和最重要的字节:

#define LSB(x) ((x) & 0x000000FF)

#define MSB(x) ((x) & 0xFF000000)
Run Code Online (Sandbox Code Playgroud)

我的问题是:上面两个函数在big endian和little endian机器上返回正确的结果吗?

现在我将解释为什么我有困惑.想象一下,我们正在使用一台小型机器.在一个小端机器上,整数9存储在内存中,如下所示(十六进制):09 00 00 00(最低有效字节优先)现在在某些时候,您可能会认为,如果我们使用上面的LSB函数,那么我们最终会得到这样的表达式:09 00 00 00和00 00 00 FF为0 - 但当然不是LSB函数最终会如何工作.所以我似乎错过了什么.任何帮助赞赏.

另外,如果我说int y = 0x000000FF- 无论机器的endiannes是什么,这都是255?

Sha*_*baz 11

无论字节顺序如何,x & 0xFF都会为您提供最不重要的字节.

首先,您应该了解字节序和重要性之间的区别.字节顺序表示将字节写入内存的顺序; 它与CPU中的任何计算完全无关.意义说明哪些位具有更高的值; 它与任何存储系统完全无关.

一旦将值从内存加载到CPU中,它的字节顺序无关紧要,因为对于CPU(更准确地说,ALU)而言,重要的是位的重要性.

因此,就C而言,0x000000FF在其最低有效字节中具有1,并且and使用变量将其赋予其最低有效字节.


事实上,在整个C标准中,你找不到"endian"这个词.C定义了一个"抽象机器",其中只有比特的重要性才重要.编译器负责编译程序,使其行为与抽象机器相同,无论字节顺序如何.因此,除非您期望某种内存布局(例如通过一个union或一组指针),否则您根本不需要考虑字节序.


您可能感兴趣的另一个例子是转移.同样的事情适用于转移.事实上,就像我之前所说的那样,字节序对ALU来说无关紧要,所以<<总是转换为甚至不是编译器转向更重要的位,而是CPU本身,无论字节顺序如何.


让我把它们放在一个带有两个正交方向的图形中,这样你可能会更好地理解它.这是从CPU的角度看加载操作的样子.

在小端机器上你有:

         MEMORY            CPU Register

  LSB BYTE2 BYTE3 MSB  ---->   MSB
    \    \     \----------->  BYTE3
     \    \---------------->  BYTE2
      \-------------------->   LSB
Run Code Online (Sandbox Code Playgroud)

在大端机器上你有:

         MEMORY            CPU Register

      /-------------------->   MSB
     /    /---------------->  BYTE3
    /    /     /----------->  BYTE2
  MSB BYTE3 BYTE2 LSB  ---->   LSB
Run Code Online (Sandbox Code Playgroud)

如您所见,在这两种情况下,您都有:

CPU Register

    MSB
   BYTE3
   BYTE2
    LSB
Run Code Online (Sandbox Code Playgroud)

这意味着在两种情况下,CPU最终加载完全相同的值.