c++中的算术与逻辑移位操作

Arithmetic vs logical shift operation in C++

本文关键字:位操作 c++      更新时间:2023-10-16

我有一些代码,用左移操作符将各种长度的参数(u8, u16, u32)填充到u64中。

然后在代码的各个地方,我需要从这个臃肿的参数中得到原始参数。

只是想知道,在代码中,我们应该如何确保它是逻辑右移而不是算术右移,同时返回原始参数。

所以问题是有任何#defs或其他方法来确保和检查编译器是否会搞砸?

下面是c++代码:

u32 x , y ,z;
u64 uniqID = 0;
u64 uniqID = (s64) x << 54 |
             (s64) y << 52 |
             (s64) z << 32 |
             uniqID;  // the original uniqID value.

然后在返回值的时候:

z= (u32) ((uniqID >> 32 ) & (0x0FFFFF)); //20 bits 
y= (u32) ((uniqID >> (52 ) & 0x03));     //2 bits
x= (u32) ((uniqID >> (54) & 0x03F));     //6 bits

一般规则是逻辑移位适用于无符号二进制数,而算术移位适用于有符号2的比较数。这将取决于你的编译器(gcc等),而不是语言,但你可以假设编译器将对无符号数使用逻辑移位…所以如果你有一个无符号类型,你会认为这是一个逻辑转换。

如果您需要在编译器之间进行一些可移植性,您总是可以编写自己的方法来检查和执行转换。或者您可以使用内联asm来做到这一点并避免任何问题(但是您将被固定到一个平台上)。

简而言之,要100%正确,请检查编译器文档。

这看起来像C/c++,所以只要确保uniqID是无符号整数类型。

或者,直接转换它:

z = (u32) ( ((unsigned long long)uniqID >> (32) & (0x0FFFFF));  //20 bits 
y = (u32) ( ((unsigned long long)uniqID >> (52) & 0x03)) ; //2 bits
x = (u32) ( ((unsigned long long)uniqID >> (54) & 0x03F)) ;  //6 bits