如果我右移,我必须将最高有效位设置为零吗?



假设我有一个64位的数字,并且设置了一些位来保存一个值,假设是3位。我有一个遮罩来获取这个值。为了得到这三个比特的值,我将数字与掩码按位"与"。这将所有其他位置零。然后我需要向右移动到最低有效位,这样3位数字的最低有效位就在64位数字的最低有效位的位置上。在我向右移动之后,我是否需要再次掩码以确保这三个位的左边的所有位都是零?

你可以先做shift,然后做蒙版,完成你想要的:

int value = 0xdeadbeef;
value >>= 15;
value &= 0x7;

在以前的c++标准版本中,负值的右移是由实现定义的,因为有符号整数可以是一补数、二补数或符号+幅度。因此,负数的右移行为是实现定义的。

但是(现代)c++的所有实现都是针对使用双补码的cpu的,并且许多现有代码依赖于该实现细节。在c++ 2020中,这最终得到了承认,并且有符号整数现在被定义为两个补码。

右移的工作方式取决于实参的类型:

int value = -1;
value >>= 10;

假设现在需要两个补码,这将使用算术移位并保留符号位。所以在移位之后,值仍然是-1,并且所有位都设置好了。如果你在移位前掩码,那么移位后你得到的比特会比你所期望的要多。

unsigned int value = 0xFFFFFFFF;
value >>= 10;

这将使用逻辑移位并在左边加零。因此,如果在移位之前进行掩码,那么在移位之后仍然可以得到正确的位。

但是为什么要在换班前戴口罩呢?如果在移位之后进行掩码,那么无论类型如何,都能得到正确的位。

如果我右移,我必须将最高有效位设置为零吗?
右移后,我是否需要再次掩码以确保只有这三个位左边的所有位都为零?

是的,如果掩码的结果是有符号类型,则掩码需要处理符号位移位。

如果掩码的结果是unsigned类型,则返回No。

uint64_t mask = ...;
uint64_t masked_value = mask & value;
uint64_t final = masked_value >> shift_amount; 

If code did:

int64_t mask = 7 << shift_amount;
int64_t masked_value = mask & value;
int64_t almost_final = masked_value >> shift_amount; 
int final = (int) (masked_value & 7); 

一个聪明的编译器可以像上面的unsigned方法一样高效。

相关内容

  • 没有找到相关文章

最新更新