如何正确取消64位数位?

Sko*_*ler -1 c++ bit

我想设置64位数的全部,部分或无位.但是当我打印位表示时,例如我只设置了53位,我看,所有位都是1.可能是什么问题?

int main() {

  uint64_t a = 0;
  for (int i = 0; i <= 63; i++)
    std::cout<<((a>>i) & 0x01)<<" ";
  std::cout<<std::endl;
  for (unsigned i = 0; i <= 52; i++)
    a |= (1<<i);
  for (int i = 0; i <= 63; i++)
    std::cout<<((a>>i) & 1)<<" ";
  std::cout<<std::endl;
}
Run Code Online (Sandbox Code Playgroud)

编辑:我得到这个输出:

0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0

1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

但是最后一个改变了,不应该包括所有那些.

n. *_* m. 8

1是一个字面的类型int.如果您的计算机具有32位ints,(1<<i)则会为i大于30的所有计算机调用未定义的行为.

如果您想使用uint64_t,请始终这样做.

a |= (static_cast<uint64_t>(1)<<i);
Run Code Online (Sandbox Code Playgroud)

或者干脆

a |= (1ULL<<i);
Run Code Online (Sandbox Code Playgroud)

会做的伎俩.


Sto*_*ica 5

程序的行为未定义.因此,就C++而言,无论你看到什么结果都是完全有效的.

显而易见的原因是,(1<<i)由于常量1是int,因此是int.并且未定义超过位限制的int(有符号类型)的移位操作.

所以你需要强制表达std::uint64_t.一种这样的方式是这样的:

constexpr std::uint64_t one = 1;

// ...

for (unsigned i = 0; i <= 52; i++)
  a |= (one << i);
Run Code Online (Sandbox Code Playgroud)