1

我试图将一个 int 变量拆分为任意长度的两部分(即:将 32 位拆分为 31 位和 1 位、30 位和 2 位、16 位和 16 位、1 位和 31 位等)。

我曾尝试使用按位移位运算符来实现它,但似乎无法使其正常工作。

int botLength = 4;
int start = ~0;
int top = start << botLength;
int bottom = start - top;

std::cout << "Top:    " << std::bitset<32>(top) << std::endl;
std::cout << "Bottom: " << std::bitset<32>(bottom) << std::endl;

这输出

Top:    11111111111111111111111111110000
Bottom: 00000000000000000000000000001111

我想要的地方:

Top:    00001111111111111111111111111111
Bottom: 00000000000000000000000000001111    

我想我可以通过将代码更改为以下内容来解决此问题:

int botLength = 4;
int start = ~0;
int top = start << botLength;
int bottom = start - top;
top = top >> botLength; //added this

std::cout << "Top:    " << std::bitset<32>(top) << std::endl;
std::cout << "Bottom: " << std::bitset<32>(bottom) << std::endl;

然而,这似乎添加了 1 作为填充,因为它输出:

Top:    11111111111111111111111111111111
Bottom: 00000000000000000000000000001111

任何人都可以提出解决此问题的方法吗?

4

3 回答 3

2

您应该使用无符号值uint32_t来解决您的问题。使变量top无符号。


变量top已在您的代码中签名

int botLength = 4;
int start = ~0;
int top = start << botLength;

上面的代码在 中输入一个负值top,那么最左边的符号位(最高有效位)就是1

int bottom = start - top;
top = top >> botLength;

每次右移保持符号后,符号位将1重新置位。所以,你有所有的位1


总之,编译器尝试在每次移位操作后保留有符号整数值的符号。所以,这种机制会影响你的算法,你不会得到正确的结果。

于 2013-11-04T19:08:40.150 回答
2

因为在 C 和 C++int中被视为有符号数,所以右移运算符复制最高有效位,它表示符号。有符号数以二进制补码编码。

您应该切换到unsigned以在右移时清除最高位,或者您也可以动态使用强制转换,例如:

unsigned bits = 1;
int s = -1;
s = s >> bits;

int u = -1;
u = unsigned(u) >> bits;

在此之后,s 将是 -1 (0xFFFFFFFF),而 u 将是 2147483647 (0x7FFFFFFF)

于 2013-11-04T19:20:22.100 回答
0

有符号值的最高有效位指示该值是负数还是正数。正如 M M. 所指出的,如果您右移一个负数,则该操作会将符号位扩展到高位。

除以 2 相当于右移一位。如果你将 -4 除以 2,你会期望得到 -2,而不是 6,如果你不扩展符号,我认为你会得到 6。

于 2013-11-04T19:20:01.113 回答