C++ 奇怪的行为设置位

C++ 奇怪的行为设置位,c++,binary,C++,Binary,我正在研究一个系统,它要求我能够设置组成整数类型的各个位 我写了一个程序来测试一些二进制运算符的用法。下面是一个使用二进制或运算符将位设置为true的小示例。但我对这种行为感到困惑。如果我循环,将每个位设置为true,它会在第31位之后突然将所有位设置为true。考虑到我在一台64位机器上,并且我正在使用数值限制来获取位数,我不确定为什么会出现这种情况 #include <iostream> #include <bitset> #include <limits>

我正在研究一个系统,它要求我能够设置组成整数类型的各个位

我写了一个程序来测试一些二进制运算符的用法。下面是一个使用二进制或运算符将位设置为true的小示例。但我对这种行为感到困惑。如果我循环,将每个位设置为true,它会在第31位之后突然将所有位设置为true。考虑到我在一台64位机器上,并且我正在使用
数值限制
来获取位数,我不确定为什么会出现这种情况

#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;
}

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

这是积分扩张的两种不同行为。积分扩展是当一个积分类型转换成一个更大的积分类型时所发生的事情:计算机显然不能仅仅使新的位随机,因此编译器选择两个一致的行为之一

  • 符号扩展接受符号位并对该整数的所有新位重复它:这样,如果你接受一个
    int
    并使其成为
    long
    ,它仍然是具有相同符号的相同数字。这是扩展有符号整数时通常发生的情况
  • 零扩展用零代替,无论数字是什么,现在都是正数(但如果是正数,则保持不变)。这是扩展无符号整数时通常发生的情况,对于无符号整数,将符号位视为常规数字位

您还需要告诉编译器1至少与
变量一样大,因为否则,当您移位时,1将“脱落”:您将其移位到大于int的大小,因此它将被丢弃。您可以通过将
1
强制转换为
ullong
(ullong)1
),或者更简单地说,使用
ull
前缀:
1ull
,这是因为1被视为整数,因此,当它扩展为64位整数时,它是符号扩展的。无符号整数改为零扩展

这是积分扩张的两种不同行为。积分扩展是当一个积分类型转换成一个更大的积分类型时所发生的事情:计算机显然不能仅仅使新的位随机,因此编译器选择两个一致的行为之一

  • 符号扩展接受符号位并对该整数的所有新位重复它:这样,如果你接受一个
    int
    并使其成为
    long
    ,它仍然是具有相同符号的相同数字。这是扩展有符号整数时通常发生的情况
  • 零扩展用零代替,无论数字是什么,现在都是正数(但如果是正数,则保持不变)。这是扩展无符号整数时通常发生的情况,对于无符号整数,将符号位视为常规数字位

您还需要告诉编译器1至少与
变量一样大,因为否则,当您移位时,1将“脱落”:您将其移位到大于int的大小,因此它将被丢弃。您可以通过将
1
强制转换为
ullong
(ullong)1
),或者更简单地说,使用
ull
前缀:
1ull
,从5.8移位运算符开始

操作数应为整数或无范围枚举类型,且 执行整体促销。结果的类型是 提升后的左操作数。如果正确,则该行为未定义 操作数为负数,或大于或等于以位为单位的长度 提升后的左操作数


麻烦从我32岁开始。换句话说,来自5.8移位运算符的int32_t(1)

操作数应为整数或无范围枚举类型,且 执行整体促销。结果的类型是 提升后的左操作数。如果正确,则该行为未定义 操作数为负数,或大于或等于以位为单位的长度 提升后的左操作数


麻烦从我32岁开始。换句话说,int32_t(1)
1
是一个整数,您正在溢出它。请尝试使用
1all
。为什么不使用
std::bitset
?我的意思是,为什么不首先使用它?我不使用bitset,因为在最终实现中,它必须是线程安全且无锁的。我实际使用的是
std::atomic
,因为不能保证std::位集上的无锁操作。我没有把原子的东西放进去,因为它给问题增加了不必要的细节。
1
是一个整数,你把它溢出了。请尝试使用
1all
。为什么不使用
std::bitset
?我的意思是,为什么不首先使用它?我不使用bitset,因为在最终实现中,它必须是线程安全且无锁的。我实际使用的是
std::atomic
,因为不能保证std::位集上的无锁操作。我没有把原子元素放在里面,因为它给问题增加了不必要的细节。
I
从来没有转换成64位无符号整数,它被用作移位计数。是的,是倒过来的。值得注意的是,当左移位尝试手动填充符号位时,行为通常是未定义的。这发生在我们还没开始讨论扩大符号转换的问题之前。左移1位有效地被视为2的乘法。一旦乘法超出了底层有符号类型的范围,行为就没有定义。这就是上面的代码所演示的。从语言的角度来看,迪特的答案是正确的。
i
从不转换为64位无符号整数,它被用作移位计数。是的,倒过来了。值得注意的是
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