【问题标题】:Convert a uint16_t to bytes and vice versa - independent of system endianness将 uint16_t 转换为字节,反之亦然 - 与系统字节序无关
【发布时间】:2019-04-20 22:23:53
【问题描述】:

通过 SO 搜索,我发现我可以执行以下操作以从 uint16_t 中提取字节,然后将它们重新组合为原始数字:

uint16_t x = 700;

// extract the bytes
uint8_t byte1 = (x >> 8) & 0xFF;
uint8_t byte2 = x & 0xFF;

// reassemble
uint16_t y = (byte1 << 8) + byte2;

但据我了解 - 这仅适用于小端系统,不适用于大端系统。

有没有办法独立于系统的字节序来实现相同的事情?

【问题讨论】:

  • 不,这适用于任何系统。
  • 字节顺序无关紧要。 16 位值的位 0..7 始终是最低有效位。决定字节顺序的是它存储在内存中的序列。
  • @KamilCuk "这将适用于任何系统" --> 也许。当bytes1 &gt;= 128int 是16 位时,byte1 &lt;&lt; 8 是UB。然而,我从未见过性能不如预期的 16 位系统。 uint16_t y = (1u*byte1 &lt;&lt; 8) + byte2; 是一种便携式替代品。

标签: c bitwise-operators endianness


【解决方案1】:

您的代码不依赖于字节序。当使用掩码查看变量位时,它们总是看起来是大端的。高位字节将出现在低位字节的左侧。即使在 little-endian 机器上它们被交换了,我们也并不聪明。

但是,话虽如此,您可以直接复制字节而不实际查看它们。没有掩码,没有移位,只需复制字节:

// extract the bytes
uint8_t bytes[sizeof(x)];
memcpy(bytes, &x, sizeof(x));

// reassemble
uint16_t y;
memcpy(&y, bytes, sizeof(y));

【讨论】:

  • 此代码的 _intermediate 结果bytes[] 依赖于字节序。希望这对于 OP 和“......独立于系统字节序”目标来说是可行的。
  • @chux Endianess 无关紧要。无论字节顺序如何,它都会正确存储和恢复值。除非字节在不同字节序的系统之间存储和恢复或传输。 OP 的原始代码也是如此。
【解决方案2】:

字节序决定了数字在内存中的存储方式。 但是,当数字从内存加载到寄存器时,它与字节序无关。对输入数字的所有操作都是通过寄存器进行的,结果根据字节序存储回内存。

Eg. 
Number = 0xAABB

                 Memory Address        Value
Little Endian    0x3000                0xBB
                 0x3001                0xAA

Big Endian       0x3000                0xAA
                 0x3001                0xBB

但是当加载到 32 位寄存器中时,数字仍然是 0xAABB,因此 uint8_t byte1 和 uint8_t byte2 将具有相同的值,而不管字节序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-30
    • 1970-01-01
    • 2021-08-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多