uint64_t bitsToInt64(char *bs) {
uint64_t r, i;
r = 0;
for(i = 0; i < 64; i++)
if(bs[i] == 1)
r |= 1LL << i;
return r;
}
int countBits64(uint64_t i) {
uint64_t x, t;
t = 0LL;
for(x = 0LL; x < 64LL; x++) {
if(i & (1LL << x))
t += 1;
}
return t;
}
char bits [] = {
0, 0, 0, 0, 1, 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,};
uint64_t mask = bitsToInt64(bits);
int nbits = countBits64(mask);
printf("%d", nbits);
上面是打印“1”。我做错了什么?
最佳答案
您对 1LL
的转移,已签名,产生 undefined behavior .因此,允许将 64 位有符号整数移位 63 位,让编译器做一些有趣的事情(比如 making daemons fly out of your nose)。
解决方案是使用1ULL << x
而不是在这种情况下。
另见 this excellent article来自 LLVM 的 Chris Lattner,他解释了为什么这样的事情会导致奇怪的行为。
关于长时间计数位无法按预期工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6540026/