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

时间:2011-10-06 05:31:15

标签: c++ math compiler-construction bit-shift

我有一些代码用不同长度的参数(u8,u16,u32)填充到带左移位运算符的u64中。

然后在代码中的不同位置,我需要从这个大膨胀参数中取回原始参数。

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

所以qestion是否有任何#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 个答案:

答案 0 :(得分:1)

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

如果您需要编译器之间的某些可移植性,您始终可以编写自己的方法来检查并进行转换。或者您可以使用内联asm来执行此操作并避免任何问题(但您将被修复到平台)。

简而言之,要100%正确,请检查您的编译器doco。

答案 1 :(得分:1)

这看起来像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