首页 > 解决方案 > 是否有一种独立于体系结构的方法来从 C 中的值创建小端字节流?

问题描述

我试图通过创建一个 uint8_t[] 缓冲区然后发送它来在架构之间传输值。为了确保它们被正确传输,规范是在所有值进入缓冲区时将它们转换为 little-endian。

我在这里阅读了这篇文章,其中讨论了如何从一种字节序转换为另一种字节序,在这里它讨论了如何检查系统的字节序。

我很好奇是否有一种方法可以以小端顺序从 uint64 或其他值读取字节,而不管系统是大还是小?(即通过一些位操作序列)

或者是首先检查系统字节序的唯一方法,然后如果大显式转换为小?

标签: cendianness

解决方案


这实际上很简单——您只需使用转换在“本机”格式(无论是什么)和小端格式之间进行转换

/* put a 32-bit value into a buffer in little-endian order (4 bytes) */
void put32(uint8_t *buf, uint32_t val) {
    buf[0] = val;
    buf[1] = val >> 8;
    buf[2] = val >> 16;
    buf[3] = val >> 24;
}

/* get a 32-bit value from a buffer (little-endian) */
uint32_t get32(uint8_t *buf) {
    return (uint32_t)buf[0] + ((uint32_t)buf[1] << 8) +
           ((uint32_t)buf[2] << 16) + ((uint32_t)buf[3] << 24);
}

如果将一个值放入缓冲区,将其作为字节流传输到另一台机器,然后从接收到的缓冲区中获取该值,则两台机器将具有相同的 32 位值,无论它们是否具有相同或不同的本机字节骑马。需要强制转换,因为默认促销只会转换为int,它可能小于 a uin32_t,在这种情况下,移位可能超出范围。

char如果您的缓冲区不是(char 可能会或可能不会被签名),请小心uint8_t- 在这种情况下您需要屏蔽:

uint32_t get32(char *buf) {
    return ((uint32_t)buf[0] & 0xff) + (((uint32_t)buf[1] & 0xff) << 8) +
           (((uint32_t)buf[2] & 0xff) << 16) + (((uint32_t)buf[3] & 0xff) << 24);
}

推荐阅读