C 关于小端点和大端点的混淆

C 关于小端点和大端点的混淆,c,bitwise-operators,C,Bitwise Operators,我对小端点/大端点有些困惑。好像我失踪了 很简单。感谢一些反馈。 例如,假设我们有两个函数,分别检索 32位值: #define LSB(x) ((x) & 0x000000FF) #define MSB(x) ((x) & 0xFF000000) 我的问题是:上述两个函数在big-endian和little-endian机器上都返回正确的结果吗 现在我将解释为什么我会感到困惑。 想象一下我们在一台小小的endian机器上。在小端机器上,整数9存储在内存中,如下所示(十六进制

我对小端点/大端点有些困惑。好像我失踪了 很简单。感谢一些反馈。 例如,假设我们有两个函数,分别检索
32位值:

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

#define MSB(x) ((x) & 0xFF000000)
我的问题是:上述两个函数在big-endian和little-endian机器上都返回正确的结果吗

现在我将解释为什么我会感到困惑。 想象一下我们在一台小小的endian机器上。在小端机器上,整数9存储在内存中,如下所示(十六进制):09 00 00(最低有效字节优先) 现在在某个时刻,你们可能会想,若我们使用上面的LSB函数,那个么我们将结束 使用这样的表达式:0900&00FF,它是0-但当然这不是上面的LSB函数最终的工作方式。看来我错过了smth。谢谢你的帮助


另外,如果我说
int y=0x000000FF
-这是255,与机器的尾数无关,对吗?

0x000000FF
始终是255,与尾数无关。它在little endian机器上存储为
FF 00
,因此
LSB(9)
将继续工作。

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


因此,
0x000000FF
始终是255,并且您的
LSB
MSB
宏是正确的。

是的,无论是否结束,这些宏都正常工作

作为掩码使用的数字和作为输入的数字都具有相同的endianess,因此无论哪种方式,它们都给出相同的结果

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

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


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

无论是否为endianness,
x&0xFF
将为您提供最低有效字节

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

一旦您将一个值从内存加载到CPU中,它的终止性就不重要了,因为对CPU(更准确地说,ALU)来说,重要的是位的重要性

因此,就C而言,
0x000000FF
在其最低有效字节中有1s,并且
使用变量将给出其最低有效字节


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



另一个你可能感兴趣的例子是转移。同样的道理也适用于换档。事实上,正如我之前所说,Endian对ALU并不重要,因此
Endian是关于如何使用内存的。在将字节序列化或反序列化到内存、存储器或某种流时,您主要需要担心这个问题


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

,也许这会让你更清楚,问题的哪一部分是我最困惑的。(例如,我谈论09 00&00 FF的地方)@dmcr_代码,我已经解决了您的困惑。事实上,
0x0000009
作为
09 00
存储在内存中,但ALU仍然将其视为
0x0000009
。对于ALU来说,没有所谓的持久性,只有意义。当您将寄存器加载/存储到内存中时,endianness会得到处理,但这只是存储问题,而不是处理问题。数据存储在硬盘之间,但这只是存储的一个细节。所有应用程序都会一致地查看数据,因为底层系统负责存储和恢复数据。endianness也是一样。这是CPU期望数据如何在内存中布局的问题,但除了在内存中存储/恢复数据的过程之外,没有endianness这个词。好的,你的基本意思是,即使在little endian系统上,9是这样存储在内存中的:09 00 00,当我将它传递给实际的LSB宏时,它已经被解释为数字0x000009-这就是你的意思,对吗?@dmcr_code,完全正确。在处理过程中,存储并不重要。因此,如果您的号码是
0x00000009
,即使内存将其存储为,它仍然是
0x00000009
,并且
使用
0x000000FF
将为您提供
9
。似乎我对其他信息感到困惑。这一部分我已经在我谈论09 00&00 FF的段落中解释过了。。etc.OT:它不应该是
#定义MSB(x)((x)&0xFF000000)>>24)
还是只
#定义MSB(x)((x)>>24)
(假设传递了32位值)?您可能会这样做
         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