8

我对小端/大端有些困惑。似乎我缺少简单的东西。一些反馈表示赞赏。例如,假设我们有两个函数可以检索
32 位值的最低和最高有效字节:

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

#define MSB(x) ((x) & 0xFF000000)

我的问题是:以上两个函数是否在大端小端都返回正确的结果端机器

现在我将解释为什么我会感到困惑。想象一下我们在一个小端机器上。在小端机器上,整数 9 像这样(十六进制)存储在内存中: 09 00 00 00 (最低有效字节在前) 现在,你可能会想,如果我们使用上面的 LSB 函数,那么我们最终会得到这样的表达式: 09 00 00 00 & 00 00 00 FF 是 0 - 但当然这不是 LSB 函数最终将如何工作的方式。所以看来我错过了。任何帮助表示赞赏。

另外,如果我说int y = 0x000000FF-无论机器的字节序如何,这都是 255 对吗?

4

6 回答 6

12

不管字节顺序如何,x & 0xFF都会给你最低有效字节。

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

一旦将内存中的值加载到 CPU 中,字节序就无关紧要了,因为对于 CPU(更准确地说,ALU)来说,重要的是位的重要性。

因此,就 C 而言,0x000000FF在其最低有效字节中有 1,并且and用变量对其进行 ing 将给出其最低有效字节。


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


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


让我把它们放在一个有两个正交方向的图中,也许你会更好地理解它。从 CPU 的角度来看,这就是加载操作的样子。

在 little-endian 机器上,您有:

         MEMORY            CPU Register

  LSB BYTE2 BYTE3 MSB  ---->   MSB
    \    \     \----------->  BYTE3
     \    \---------------->  BYTE2
      \-------------------->   LSB

在大端机器上,您有:

         MEMORY            CPU Register

      /-------------------->   MSB
     /    /---------------->  BYTE3
    /    /     /----------->  BYTE2
  MSB BYTE3 BYTE2 LSB  ---->   LSB

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

CPU Register

    MSB
   BYTE3
   BYTE2
    LSB

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

于 2013-10-16T16:33:39.587 回答
3

0x000000FF无论字节顺序如何,始终为 255。它存储FF 00 00 00小端机器上,因此LSB(9)将继续工作。

于 2013-10-16T16:30:34.193 回答
1

是的,无论字节顺序如何,这些都可以正常工作。

您用作掩码的数字和您作为输入提供的数字都具有相同的字节序,因此它们给出相同的结果。

当您(例如)通过网络连接收到一个整数作为chars 数组时,字节序主要成为一个问题。在这种情况下,您必须以char正确的顺序将这些 s 重新组合在一起以获得原始值。

于 2013-10-16T16:30:55.163 回答
1

我的问题是:以上两个函数在大端和小端机器上都返回正确的结果吗?

是的,他们有。当您想从一个不是您正在做的多字节数组中形成一个标量时,问题就来了。

于 2013-10-16T16:30:58.287 回答
0

只要您将整数值视为单个实体而不是原始字节序列(在内存中,在线等),字节序问题就不会出现在您的代码中。

因此,0x000000FF总是 255 并且您的LSBMSB宏是正确的。

于 2013-10-16T16:30:47.840 回答
0

Endian 是关于如何使用内存的。在将字节序列化或反序列化到内存、存储或某种流时,您主要需要担心它。

我相信您的宏有时会工作,有时会按预期工作,具体取决于您使用它们的方式。如果 x 是一个 int(假设您使用的是 32 位整数),那么您应该没问题,因为编译器知道什么是 int 以及当 x 不是 32 位数字时它是如何表示的,您可能会遇到问题。

于 2013-10-16T16:37:48.833 回答