将 int 转换为字节数组时的 C++ 字节顺序
C++ byte order when casting int to byte array
鉴于我的平台是小尾数法,我假设四字节整数值 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)或语言是否抽象出字节顺序?怎么回事?
Little endian 表示最低有效位在前,因此在内存中您将有 0x00000001
对应 1
。请注意,"first" 在这里表示在右边,因为那是截断发生的地方。如果将该 32 位整数转换为 8 位整数,您将得到最右边的部分(即 0x01
)。
你的假设被推翻了。在小尾数法中,一个 32 位整数值 1 在十六进制中表示为 0x00000001
,但在字节中表示为 0x01 0x00 0x00 0x00
.
你说,
Given that my platform is little endian, I assumed that a four-byte integer value of 1 would be represented as 0x00
, 0x00
, 0x00
, 0x01
when expressed as a byte array.
不正确的假设。那将是大端系统。参见 http://en.wikipedia.org/wiki/Endianness#Big-endian。
小端意味着您首先写入或存储数字的最低有效位。大端意味着您首先写入或存储最高有效位。
想想我们通常在纸上写数字的方式。在纸上写10进制数4823时,我们写的是big-endian。第一个数字 4 是千位数字。我们称它为最高有效位,因为它对数字的大小影响最大。第二个数字 8 是百位数字。第三个数字 2 是十位数。第四个(也是最后一个)数字 3 是个位(或单位)数字。我们称个位数字最不重要,因为它对数字大小的影响最小。
一个四字节(32 位)整数以 256 为基数存储在内存中。每个字节是一个数字,但数字范围是从 0 到 255,而不是仅仅从 0 到 9。
小端平台首先存储最低有效字节,即个位。 256s 数字是第二个字节。 65536s 数字是第三个字节。 16777216s 数字是第四位(也是最后一位)。
因此,在您的示例中,我们可以将纸上的数字写为 0x00000001(因为我们几乎总是将数字写在纸上大端),但在小端系统上,字节(以 256 为基数)存储在顺序 01 00 00 00
.
(请注意,我们无法在大多数系统上直接寻址单个位。因此,无法在机器代码级别判断字节中的各个位是存储在小端还是大端,或者是否这在硬件层面上什至是一个有意义的概念。这就是为什么我说数字存储在基数 256 中,而不是基数 2。)
鉴于我的平台是小尾数法,我假设四字节整数值 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)或语言是否抽象出字节顺序?怎么回事?
Little endian 表示最低有效位在前,因此在内存中您将有 0x00000001
对应 1
。请注意,"first" 在这里表示在右边,因为那是截断发生的地方。如果将该 32 位整数转换为 8 位整数,您将得到最右边的部分(即 0x01
)。
你的假设被推翻了。在小尾数法中,一个 32 位整数值 1 在十六进制中表示为 0x00000001
,但在字节中表示为 0x01 0x00 0x00 0x00
.
你说,
Given that my platform is little endian, I assumed that a four-byte integer value of 1 would be represented as
0x00
,0x00
,0x00
,0x01
when expressed as a byte array.
不正确的假设。那将是大端系统。参见 http://en.wikipedia.org/wiki/Endianness#Big-endian。
小端意味着您首先写入或存储数字的最低有效位。大端意味着您首先写入或存储最高有效位。
想想我们通常在纸上写数字的方式。在纸上写10进制数4823时,我们写的是big-endian。第一个数字 4 是千位数字。我们称它为最高有效位,因为它对数字的大小影响最大。第二个数字 8 是百位数字。第三个数字 2 是十位数。第四个(也是最后一个)数字 3 是个位(或单位)数字。我们称个位数字最不重要,因为它对数字大小的影响最小。
一个四字节(32 位)整数以 256 为基数存储在内存中。每个字节是一个数字,但数字范围是从 0 到 255,而不是仅仅从 0 到 9。
小端平台首先存储最低有效字节,即个位。 256s 数字是第二个字节。 65536s 数字是第三个字节。 16777216s 数字是第四位(也是最后一位)。
因此,在您的示例中,我们可以将纸上的数字写为 0x00000001(因为我们几乎总是将数字写在纸上大端),但在小端系统上,字节(以 256 为基数)存储在顺序 01 00 00 00
.
(请注意,我们无法在大多数系统上直接寻址单个位。因此,无法在机器代码级别判断字节中的各个位是存储在小端还是大端,或者是否这在硬件层面上什至是一个有意义的概念。这就是为什么我说数字存储在基数 256 中,而不是基数 2。)