我对位操作有点陌生。我正在尝试将信息存储在 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,它也会失败。为什么?
我对位操作有点陌生。我正在尝试将信息存储在 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,它也会失败。为什么?
表达式的类型通常由表达式本身决定,而不是由它出现的上下文决定。
你的变量u
是类型的int64_t
(顺便说一下,uint64_t
因为你正在执行按位运算会更好)。
在这一行:
u |= 1 << i;
既然1
是类型int
,1 << i
也是类型int
。如果通常int
是 32 位,则对于较大的i
.
如果将此行更改为:
u |= (uint64_t)1 << i;
它应该做你想做的事。
您也可以将 更改1
为1ULL
。这给它一种类型unsigned long long
,保证至少为 64 位,但不一定与uint64_t
.
当您移入 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;