C ++ - 将int拆分为两个较小的数据类型

时间:2013-11-04 19:04:05

标签: c++ split bit-manipulation

我试图将一个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

有人可以建议一种解决方法吗?

3 个答案:

答案 0 :(得分: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


总之,编译器尝试在每次移位操作后保持有符号整数值的符号。因此,这种机制会影响您的算法,您将无法获得正确的结果。

答案 1 :(得分:2)

因为在C和C ++中int被视为带符号的数字,所以右移位运算符复制最高有效位,表示符号。签名号码以Two's complement编码。

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

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

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

之后,s将为-1(0xFFFFFFFF),而u将为2147483647(0x7FFFFFFF)

答案 2 :(得分:0)

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

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