Подсчет битов в длинном длинном не работает, как ожидалось - PullRequest
1 голос
/ 30 июня 2011
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". Что я делаю не так?

Ответы [ 2 ]

2 голосов
/ 30 июня 2011

Ваше смещение 1LL, которое подписано, дает неопределенное поведение .Таким образом, сдвиг 64-битного знакового целого числа на 63 бита позволяет компилятору делать забавные вещи (например, заставляет демонов вылетать из носа ).

Решениевместо этого использовать 1ULL << x.

См. также эту превосходную статью от Криса Латтнера из LLVM, в которой объясняется , почему подобные вещи могут привести к странному поведению.

1 голос
/ 30 июня 2011

С кодом ниже я смог получить следующий вывод

(0xFF00000000000010) 9

Убедитесь, что вы используете правильные значения размера. Для литеральных констант необходимо ULL, чтобы они соответствовали uint64_t, а переменные цикла for должны быть только целыми числами, а также возвращаемым значением для 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);
...