C 字节反转整数的问题
祝你好运 有人能解释一下字节反转函数这两种实现的逻辑区别吗 例1:C 字节反转整数的问题,c,endianness,C,Endianness,祝你好运 有人能解释一下字节反转函数这两种实现的逻辑区别吗 例1: uint32_t byte_reverse_32(uint32_t num) { static union bytes { uint8_t b[4]; uint32_t n; } bytes; bytes.n = num; uint32_t ret = 0; ret |= bytes.b[0] << 24; ret |= bytes.b
uint32_t byte_reverse_32(uint32_t num) {
static union bytes {
uint8_t b[4];
uint32_t n;
} bytes;
bytes.n = num;
uint32_t ret = 0;
ret |= bytes.b[0] << 24;
ret |= bytes.b[1] << 16;
ret |= bytes.b[2] << 8;
ret |= bytes.b[3];
return ret;
}
uint32字节反向(uint32字节数){
静态联合字节{
uint8_t b[4];
uint32\u t n;
}字节;
字节数,n=num;
uint32_t ret=0;
ret |=bytes.b[0]您正在使用| |,这是一个布尔运算符,如果两个参数中的一个不同于零,则为true(1)
要获得正确的结果,需要按位OR运算符,即|,就像您在第一个示例中所做的那样(x |=y是x=x | y而不是x=x | | y)
因此,第二个示例应该与
ret |= (bytes.b[0] LSHIFT 24) | (bytes.b[1] LSHIFT 16) | (bytes.b[2] LSHIFT 8) | (bytes.b[3]);
希望能有所帮助。您使用的是| |这是逻辑or运算符,您需要的是二进制|运算符。
与|
不是同一个运算符。第一个是按位or,这是您需要的。第二个是布尔or,这是您所拥有的。您根本没有使用num
参数,而是相反如果您使用未初始化的字节
union变量
这里实际上不需要联合,您可以通过访问其字节的方式简单地强制转换num
参数:
uint8_t *b = (uint8_t*)#
// then access b[0] through b[3]
正如其他人已经回答的那样,使用按位|
运算符而不是|
这个问题已经得到了回答,但关于可以进入生产的代码,我只花了2美分:
在代码中使用static
关键字,如下所示:
uint32_t byte_reverse_32(uint32_t num) {
static union bytes {
uint8_t b[4];
uint32_t n;
} bytes;
/* etc.*/
没有性能值(或任何值),并且如果从多个线程调用,将确保您的函数将有数据争用(即,使用起来不安全)
请删除静态
:您的函数将同样快速且多线程安全(更简单)
需要注意的是,通过混合物理级内存访问和值级逐位操作来对整数进行字节反转的整个方法看起来非常可疑。我的意思是,这可能对您有效,但为什么有人会这样做?创建这种奇怪的混合有什么意义
如果您决定通过将整数值重新解释为4个字节的序列来进行直接物理内存访问,那么自然的反转方法是只交换字节0和3,交换字节1和2
uint32_t byte_reverse_32(uint32_t num) {
union bytes {
uint8_t b[4];
uint32_t n;
} bytes;
uint8_t t;
bytes.n = num;
t = bytes.b[0]; bytes.b[0] = bytes.b[3]; bytes.b[3] = t;
t = bytes.b[1]; bytes.b[1] = bytes.b[2]; bytes.b[2] = t;
return bytes.n;
}
另一种方法是在值级别完成整个工作,通过逐位操作实现所有内容,而无需任何内存重新解释
uint32_t byte_reverse_32(uint32_t num) {
uint32_t res;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF;
return res;
}
uint32字节反向(uint32字节数){
uint32_t res;
res=num&0xFF;num>=8;res=8;res=8;res您可能希望使用系统头(endian.h
在glibc中,sys/endian.h
和machine/endian.h
在bsd上),这些头定义了bswap\u 32
(或在稍微不同的名称下相同)对于您的体系结构,有些CPU有一条比位洗牌更快的指令
如果您已经有了32位值,或者正在从内存中读取对齐的字,那么如果您正在读取未对齐的32位值,那么在读取时按正确的顺序组合字节要比第一次读取然后交换快。它工作得很好!!!注意这里int是4字节。
输入0xAABBCCDD
输出0xDDCCBBAA
#包括
intmain()
{
int A=0x12ABCDEF;
int R=0;
R=R |((A&0x000000ff)8);
R=R |((A&0xff000000)>>24);
printf(“A是%x R是%x\n”,A,R);
返回0;
}
只需将代码块缩进四个空格(编辑器中的“0101”按钮就是这样做的)。然后您可以使用类似于的方法,您的赋值也不起作用。您应该将赋值给bytes.n
。但更好的方法是使用初始化而不是赋值。正如paercebal所说,去掉static
属性,然后使用`={.n=num}初始化变量删除伪造的static
存储说明符。这会使您的代码无偿不可重入。static
没有const
几乎总是一个错误。已编辑。从内存中匆忙键入=)。
uint32_t byte_reverse_32(uint32_t num) {
union bytes {
uint8_t b[4];
uint32_t n;
} bytes;
uint8_t t;
bytes.n = num;
t = bytes.b[0]; bytes.b[0] = bytes.b[3]; bytes.b[3] = t;
t = bytes.b[1]; bytes.b[1] = bytes.b[2]; bytes.b[2] = t;
return bytes.n;
}
uint32_t byte_reverse_32(uint32_t num) {
uint32_t res;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF; num >>= 8; res <<= 8;
res = num & 0xFF;
return res;
}
int main()
{
int A= 0x12ABCDEF;
int R=0;
R = R | ((A&0x000000ff) << 24);
R = R | ((A&0x0000ff00) << 8);
R = R | ((A&0x00ff0000) >> 8);
R = R | ((A&0xff000000) >>24);
printf("A is %x R is %x \n", A, R);
return 0;
}