2

我对位操作有点陌生。我正在尝试将信息存储在 int64_t 变量中,如下所示:

int64_t u = 0;

for(i=0;i<44;i++)
   u |= 1 << i;

for(;i<64;i++)
   u |= 0 << i;

int t = __builtin_popcountl(u);

我的意图是在变量 u 中存储 44 个 1,并确保剩余位置全部为 0,因此“t”返回 44。但是,它总是返回 64。对于其他变量,例如 int32,它也会失败。为什么?

4

3 回答 3

4

表达式的类型通常由表达式本身决定,而不是由它出现的上下文决定。

你的变量u是类型的int64_t(顺便说一下,uint64_t因为你正在执行按位运算会更好)。

在这一行:

u |= 1 << i;

既然1是类型int1 << i也是类型int。如果通常int是 32 位,则对于较大的i.

如果将此行更改为:

u |= (uint64_t)1 << i;

它应该做你想做的事。

您也可以将 更改11ULL。这给它一种类型unsigned long long,保证至少为 64 位,但不一定uint64_t.

于 2014-06-12T19:38:55.013 回答
0
  1. __builtin_popcountl 将 unsigned long 作为其参数,它并不总是 64 位整数。我个人使用__builtin_popcountll,这需要很长时间。看来你不是这种情况
  2. 默认情况下,整数具有“int”类型,并且通过将 int 移动大于或等于 32(准确地说,int 的大小以位为单位),您会得到未定义的行为。正确用法:u |= 1LL << i; 这里LL代表long long。
  3. Oring 与零什么都不做。您不能只将位设置为特定值,您应该使用掩码 OR(如果要将某些位设置为 1)或与掩码的否定(如果要将某些位设置为 0)进行与,否定由蒂尔达(〜)。
于 2014-06-12T19:37:37.540 回答
0

当您移入 32 位整数的高位并转换为 64 位时,符号位将延伸到高 32 位;然后您将设置所有 64 位,因为您的文字 '1' 默认情况下是有符号的 32 位 int。移位也不会影响高 32 位,因为该值只有 32 位;但是,当转换的值为负时,将转换为 64 位。

这可以通过编写你的第一个循环来解决,如下所示:

for(i=0;i<44;i++)
   u |= (int64_t)1 << i;

此外,这个循环什么也不做,因为与 0 的 ORing 不会改变值:

for(;i<64;i++)
   u |= 0 << i;
于 2014-06-14T15:38:24.853 回答