奇怪的行为设置位

时间:2013-12-13 16:14:35

标签: c++ binary

我正在开发一个系统,要求我能够设置构成整数类型的各个位。

我写了一个程序来测试一些二元运算符的用法。以下是使用二进制OR运算符将位设置为true的小示例。但这种行为让我很困惑。如果我循环,将每个位设置为true,它会在第31位之后突然将所有位设置为true。我不确定为什么这会考虑我在64位机器上而且我使用numeric_limits来获取位数。

#include <iostream>
#include <bitset>
#include <limits>

int main() {

  typedef unsigned long long ullong;
  ullong bits;

  for(int i = 0; i < std::numeric_limits<ullong>::digits; ++i) {
    bits |= (1 << i);
    std::cout << std::bitset<std::numeric_limits<ullong>::digits>(bits) << "\n";
  }

  return 0;
}

该程序的输出如下:

0000000000000000000000000000000000000000000000000000000000000001
0000000000000000000000000000000000000000000000000000000000000011
0000000000000000000000000000000000000000000000000000000000000111
0000000000000000000000000000000000000000000000000000000000001111
0000000000000000000000000000000000000000000000000000000000011111
0000000000000000000000000000000000000000000000000000000000111111
0000000000000000000000000000000000000000000000000000000001111111
0000000000000000000000000000000000000000000000000000000011111111
0000000000000000000000000000000000000000000000000000000111111111
0000000000000000000000000000000000000000000000000000001111111111
0000000000000000000000000000000000000000000000000000011111111111
0000000000000000000000000000000000000000000000000000111111111111
0000000000000000000000000000000000000000000000000001111111111111
0000000000000000000000000000000000000000000000000011111111111111
0000000000000000000000000000000000000000000000000111111111111111
0000000000000000000000000000000000000000000000001111111111111111
0000000000000000000000000000000000000000000000011111111111111111
0000000000000000000000000000000000000000000000111111111111111111
0000000000000000000000000000000000000000000001111111111111111111
0000000000000000000000000000000000000000000011111111111111111111
0000000000000000000000000000000000000000000111111111111111111111
0000000000000000000000000000000000000000001111111111111111111111
0000000000000000000000000000000000000000011111111111111111111111
0000000000000000000000000000000000000000111111111111111111111111
0000000000000000000000000000000000000001111111111111111111111111
0000000000000000000000000000000000000011111111111111111111111111
0000000000000000000000000000000000000111111111111111111111111111
0000000000000000000000000000000000001111111111111111111111111111
0000000000000000000000000000000000011111111111111111111111111111
0000000000000000000000000000000000111111111111111111111111111111
0000000000000000000000000000000001111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111
1111111111111111111111111111111111111111111111111111111111111111

2 个答案:

答案 0 :(得分:3)

这是因为1被视为整数,因此,当它被扩展为64位整数时,它被符号扩展。无符号整数是零扩展的。

这是积分扩展的两种不同行为。当积分类型转换为更大的整数类型时,整体扩展就会发生:计算机显然不能使新位随机,因此编译器会选择两种一致行为中的一种。

  • 符号扩展取符号位并为该整数的所有新位重复它:这样,如果你取int并使其成为long,它仍然会是具有相同符号的相同数字。这是扩展有符号整数时通常会发生的情况。
  • 使用零填充零延伸垫,无论数量是多少,它现在都是正数(但如果是正数,则保持不变)。这是扩展无符号整数时通常会发生的情况,您将符号位视为常规数字位。

您还需要告诉编译器1至少与您的bits变量一样大,因为否则1将会#34;脱落&#34;当你移动时:你将它移动到比int的大小更远的位置,所以它将被丢弃。您可以通过将1转换为ullong(ullong)1),或者更简洁地使用ull前缀1ull来实现此目的。

答案 1 :(得分:1)

来自5.8 Shift运算符

  

操作数应为整数或无范围的枚举类型   进行整体促销。结果的类型是   晋升的左操作数。如果正确,行为是不确定的   操作数是负数,或大于或等于位的长度   提升的左操作数。

当我变成32时麻烦开始。换句话说,int32_t(1)&lt;&lt; 32是未定义的行为。