[英]Counting bits in a long long not working as expected
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
的轉移會產生未定義的行為。 因此,允許將 64 位簽名的 integer 移動 63 位,以使編譯器做一些有趣的事情(比如讓守護進程飛出你的鼻子)。
解決方案是在這種情況下使用1ULL << x
。
另請參閱 LLVM 的 Chris Lattner 的這篇優秀文章,該文章解釋了為什么這樣的事情會導致奇怪的行為。
使用下面的代碼,我能夠得到以下 output
(0xFF00000000000010) 9
確保使用正確的尺寸值。 文字常量需要ULL
以便它們匹配 uint64_t 並且 for 循環變量只需要是一個 int 以及countBits64
的返回值。
uint64_t bitsToInt64(char *bs) {
uint64_t r;
int i;
r = 0;
for(i = 0; i < 64; i++)
if(bs[i] == 1)
r |= 1ULL << i;
return r;
}
int countBits64(uint64_t i) {
int x, t = 0;
for(x = 0; x < 64; x++) {
if(i & (1ULL << 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("(0x%016llX) %d",mask, nbits);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.