无论值大小,一次读取一个字节是否与字节序无关?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (7)

假设我正在uint32_t从流中读取和写入值。如果我一次向/从流读取/写入一个字节并按照下面的示例移动每个字节,那么无论机器字节顺序如何,结果都是一致的吗?

在这里的示例中,流是内存中的缓冲区,称为p

static uint32_t s_read_uint32(uint8_t** p)
{
    uint32_t value;
    value  = (*p)[0];
    value |= (((uint32_t)((*p)[1])) << 8);
    value |= (((uint32_t)((*p)[2])) << 16);
    value |= (((uint32_t)((*p)[3])) << 24);
    *p += 4;
    return value;
}

static void s_write_uint32(uint8_t** p, uint32_t value)
{
    (*p)[0] = value & 0xFF;
    (*p)[1] = (value >> 8 ) & 0xFF;
    (*p)[2] = (value >> 16) & 0xFF;
    (*p)[3] = value >> 24;
    *p += 4;
}

我目前无法访问大端机器来测试它,但想法是每个字节一次写入一个,每个字节可以独立写入或从流中读取。然后,CPU可以通过隐藏移位操作后面的这些细节来处理字节序。这是真的,如果不是,任何人都可以解释为什么不呢?

提问于
用户回答回答于

如果我一次向/从流读取/写入一个字节并按照下面的示例移动每个字节,那么无论机器字节顺序如何,结果都是一致的吗?

是。您的s_write_uint32()函数按照从最低有效到最高有效的顺序存储输入值的字节,而不管它们在该值的本机表示中的顺序。s_read_uint32()无论底层表示如何,您都可以正确地反转此过程uint32_t。这些工作是因为

  • 移位运算符(<<>>)的行为是根据左操作数的而不是其表示来定义的
  • & 0xff左边操作数的所有位的掩码,但是它的最低有效字节的掩码,不管值的表示(因为0xff有一个匹配的表示),并且
  • |=操作只是把字节到结果; 通过前面的左移,适当地选择位置。如果+=使用它可能会更清楚,但结果将没有什么不同。

但请注意,在某种程度上,你正在重新发明轮子。POSIX定义了一个函数对,htonl()并且nothl()- 在许多非POSIX系统上也支持 - 用于处理四字节数字的字节顺序问题。这个想法是,在发送时,每个人都使用htonl()从主机字节顺序(无论是什么)转换为网络字节顺序(大端)并发送生成的四字节缓冲区。收到后,每个人都接受一个数字的四个字节,然后用于ntohl()从网络转换为主机字节顺序。

用户回答回答于

它会起作用,但是memcpy后跟条件字节换行将为write函数提供更好的 codegen 。

#include <stdint.h>
#include <string.h>

#define LE (((char*)&(uint_least32_t){1})[0]) // little endian ? 
void byteswap(char*,size_t);

uint32_t s2_read_uint32(uint8_t** p)
{
    uint32_t value;
    memcpy(&value,*p,sizeof(value));
    if(!LE) byteswap(&value,4);
    return *p+=4, value;
}

 void s2_write_uint32(uint8_t** p, uint32_t value)
{
    memcpy(*p,&value,sizeof(value));
    if(!LE) byteswap(*p,4);
    *p+=4;
}

Gcc从第8个系列开始(但不是clang)可以消除小端平台上的这种转变,但是你应该通过restrict对目的地的双重间接指针进行限定来帮助它,否则它可能会认为写入(*p)[0]无效*puint8_t是一个char类型,因此允许别名)。

void s_write_uint32(uint8_t** restrict p, uint32_t value)
{
    (*p)[0] = value & 0xFF;
    (*p)[1] = (value >> 8 ) & 0xFF;
    (*p)[2] = (value >> 16) & 0xFF;
    (*p)[3] = value >> 24;
    *p += 4;
}

所属标签

可能回答问题的人

  • HKC

    红客学院 · 创始人 (已认证)

    26 粉丝7 提问5 回答
  • Dingda

    Dingda · 站长 (已认证)

    4 粉丝0 提问3 回答
  • 西风

    renzha.net · 站长 (已认证)

    9 粉丝1 提问3 回答
  • 螃蟹居

    1 粉丝0 提问2 回答

扫码关注云+社区

领取腾讯云代金券