假设我正在对流读取和写入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;
}
我目前还不能访问big-endian机器来测试这一点,但是我的想法是,如果每个字节一次写入一个字节,那么每个单独的字节都可以独立地从流中读取或写入。然后,CPU可以通过将这些细节隐藏在移位操作之后来处理字节顺序。这是真的吗?如果不是,请解释一下为什么不是这样?
发布于 2019-05-31 07:01:15
它可以工作,但一个写函数的memcpy
后跟一个条件byteswap will give you much better 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;
}
自从第8系列(但不是clang)可以在低端平台上消除这种转换,但您应该通过restrict
-qualifying指向目标的双重间接指针来帮助它,否则它可能会认为写入(*p)[0]
会使*p
无效(uint8_t
是字符类型,因此允许为任何内容指定别名)。
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;
}
https://stackoverflow.com/questions/56385192
复制相似问题