【问题标题】:C++ - Splitting int into two smaller data typesC++ - 将 int 拆分为两个较小的数据类型
【发布时间】:2013-11-04 19:04:05
【问题描述】:

我正在尝试将一个 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

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

【问题讨论】:

  • 我认为使用 unsigned int 可以解决问题,但我不完全确定。
  • 只是为了好玩,std::cout &lt;&lt; start &lt;&lt; std::endl。我想你可能会对结果感到惊讶。
  • 打印 -1,但我仍然对为什么使用 unsigned 来修复它感到困惑。无符号不只是告诉编译器如何解释数据吗?实际的二进制文件仍然应该以与 > 相同的方式受到影响(至少我是这么认为的,但它显然没有;))

标签: c++ split bit-manipulation


【解决方案1】:

您应该使用诸如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,那么如果将值向右移动,最高有效位将得到 1 而不是 0。
【解决方案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)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-12-23
      • 2014-02-21
      • 1970-01-01
      • 2013-06-22
      • 1970-01-01
      • 2015-04-20
      • 2021-03-28
      • 2012-04-06
      相关资源
      最近更新 更多