首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >无论值大小如何,一次读取一个字节的字节顺序是不可知的吗?

无论值大小如何,一次读取一个字节的字节顺序是不可知的吗?
EN

Stack Overflow用户
提问于 2019-05-31 04:27:25
回答 1查看 194关注 0票数 8

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

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

代码语言:javascript
复制
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;
}

我目前还不能访问big-endian机器来测试这一点,但是我的想法是,如果每个字节一次写入一个字节,那么每个单独的字节都可以独立地从流中读取或写入。然后,CPU可以通过将这些细节隐藏在移位操作之后来处理字节顺序。这是真的吗?如果不是,请解释一下为什么不是这样?

EN

回答 1

Stack Overflow用户

发布于 2019-05-31 07:01:15

它可以工作,但一个写函数的memcpy后跟一个条件byteswap will give you much better codegen

代码语言:javascript
复制
#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;
}

自从第8系列(但不是clang)可以在低端平台上消除这种转换,但您应该通过restrict-qualifying指向目标的双重间接指针来帮助它,否则它可能会认为写入(*p)[0]会使*p无效(uint8_t是字符类型,因此允许为任何内容指定别名)。

代码语言:javascript
复制
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;
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56385192

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档