2011-06-30 3 views
1
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); 

L'impression ci-dessus est "1". Qu'est-ce que je fais mal?Le comptage des bits sur une longue durée ne fonctionne pas comme prévu

+0

Quelle est la sortie si vous faites 'printf ("% ld ", mask);' avant la dernière ligne? – Chriszuma

+0

Je ne pense pas que ce soit le seul problème, mais vous devriez utiliser '1ULL' au lieu de' 1LL', car un '1 << 63' ne rentre pas dans un long signé. Pouvez-vous imprimer 'mask' afin que nous puissions déterminer quelle est la fonction du bug? – ughoavgfhw

+0

printf ("% llu", masque); imprime 10. Mais le bitsToInt64() doit fonctionner avant que j'utilise uint64_t en tant que bitboards pour les pièces d'échecs et ils obtiennent/règlent tous correctement ... –

Répondre

1

Avec le code ci-dessous j'ai pu obtenir le résultat suivant

(0xFF00000000000010) 9

Assurez-vous d'utiliser les valeurs de taille correcte. Les constantes littérales ont besoin de ULL pour qu'elles correspondent à uint64_t et les variables de boucle for doivent seulement être un entier, ainsi que la valeur de retour pour 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); 
+0

votre code me donne (0x00000010) 1 –

+0

Juste copié et collé encore je suis toujours obtenir ce que j'ai posté. Je cours x64 intel mac et gcc, uint64_t est typedef'd comme unsigned long long. Je suis également capable d'obtenir les mêmes résultats avec votre code original. Quel compilateur, OS, architecture êtes-vous? – Joe

+0

Juste mis à jour mon dernier commentaire, je me demande si c'est un drapeau du compilateur ou l'optimisation qui cause cela pour vous. – Joe

2

Votre déplacement de 1LL, qui est signé, les rendements undefined behavior. Déplacer un 64bit signé entier par 63 bits est donc autorisé à faire le compilateur faire des choses drôles (comme making daemons fly out of your nose).

La solution consiste à utiliser 1ULL << x à la place dans ce cas.

Voir aussi this excellent article à partir d'un Chris Lattner de LLVM qui explique pourquoi des choses comme cela peut entraîner un comportement étrange.

Questions connexes