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