C++中将整数转换为字节数组时的字节顺序问题

3

考虑到我的平台是小端字节序,我认为一个四字节整数值1应该被表示为以字节数组形式表达时的0x00, 0x00, 0x00, 0x01。因此,请有人解释一下为什么以下断言失败...

int val{1};
auto bytes = reinterpret_cast<char*>(&val);
assert(bytes[sizeof(int) - 1] == 0x01);

... 但是以下断言成功了...

assert(bytes[0] == 0x01);

在将数据强制转换为char*后,字节似乎被反转了。我的关于字节序的假设是错误的吗?编译器(clang)或语言是否抽象了字节序?到底发生了什么?


3
小端序 - 第一个字节最小 - 即第一个字节为1 - Ed Heal
小端指的是“小端先”,其中“小端”代表“最不重要的位”,而“先”则表示在内存中。 - Jean-Baptiste Yunès
4个回答

9
你的假设是错误的。在小端模式下,一个32位整数值为1的十六进制表示为0x00000001,但在字节中表示为0x01 0x00 0x00 0x00

5
小端法指的是先写或存储数字的最低有效位。大端法指的是先写或存储数字的最高有效位。 考虑我们通常在纸上写数字的方式。当我们在纸上写十进制数4823时,我们采用大端法。第一位数字4是千位数。我们称其为最重要的数字,因为它对数字的大小有最大的影响。第二位数字8是百位数。第三位数字2是十位数。第四(也是最后)一位数字3是个位数。我们称个位数为最不重要的数字,因为它对数字的大小影响最小。 一个四字节(32位)整数在内存中被存储为一个基于256的数字。每个字节是一个数字,但数字范围从0到255而不仅仅是0到9。 小端平台将最低有效字节,即个位数,首先存储。256的位数是第二个字节。65536的位数是第三个字节。16777216的位数是第四(也是最后)个字节。 因此,在您的示例中,我们可以在纸上将数字写为0x00000001(因为我们几乎总是以大端法在纸上写数字),但在小端系统上,字节(基于256的数字)按顺序存储为01 00 00 00。 (请注意,在大多数系统上无法直接访问单个位。因此,在机器代码级别上无法确定字节中的单个位是以小端法还是大端法存储的,或者这在硬件级别上是否有意义。这就是为什么我说数字以基于256的方式而不是基于2的方式存储。)

4
您说:
鉴于我的平台是小端序,我认为一个四字节的整数值1在表示为字节数组时应该表示为0x000x000x000x01
这是错误的假设。这应该是大端序系统。请参见http://en.wikipedia.org/wiki/Endianness#Big-endianenter image description here

0

小端模式意味着最不重要的数字先出现,因此在内存中,1将被表示为0x00000001。请注意,“先”在这里指的是在右边,因为那里发生了截断。如果您将32位整数强制转换为8位整数,则会得到最右边的部分(即0x01)。


从基地址开始的逐字节图可能会更清晰。在内存中,对于小端,您将拥有01 00 00 00,对于大端,您将拥有00 00 00 01。我不明白“截断”与OP的代码有什么关系,而且无论如何都是不正确的。从32位int到8位int的转换将通过值表示完成;而不是内存布局。无论您使用大端还是小端机器,static_cast<char>(int(1))都将导致一个值为0x01char - WhozCraig

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接