2014-09-22 6 views
1

Dans le cadre d'un casse-tête, je suis invité à implémenter une fonction qui vérifie si deux entrées peuvent être additionnées sans débordement. Opérations légales:! ~ &^| + < < >>.Comportement bizarre de & operator dans C

Par exemple, pour x = 0x80000000 et y = 0x80000000 la fonction doit retourner 0 car il déborde, mais pour x = 0x80000000 et y = 0x70000000 le résultat serait 1.

Ma solution à ce jour est la suivante:

int addOK(int x, int y) { 
    int mask = ~(1 << 31);  // 0x7fffffff 
    int newX = (mask & (x >> 1)); // Shift 1 to the right to make space for overflow bit 
    int newY = (mask & (y >> 1)); 
    int add = newX + newY;  // Add shifted x and y - overflow bit will be the MSB 
    int res = (add & ~mask);  // Set all bits to 0 except MSB - MSB 1 iff overflow 0 otherwise 
    int endRes = !res;   // 0x80000000 -> 0x00000000, 0x00000000 -> 0x00000001 
    printf("mask %x newX %x newY %x add %x ~mask %x res %x endRes %x\n",mask, newX, newY, add, ~mask, res, endRes); 
    return endRes; 
} 

la fonction imprime les éléments suivants pour x = 0x80000000 et y = 0x80000000:

mask 7fffffff newX 40000000 newY 40000000 add 80000000 ~mask 80000000 res 0 endRes 1 

maintenant, ma question est pourquoi est-res 0? il devrait être 0x80000000 parce que add et ~mask sont 0x80000000. Quelqu'un peut-il m'expliquer ce comportement?

+5

Impossible de reproduire: http://ideone.com/an8ocK – clcto

+3

Vous savez passer dans le bit de signe [est mauvais] (http://stackoverflow.com/questions/4009885/arithmetic-bit-shift-on-a -signed-integer), n'est-ce pas? Est-ce que vous n'utilisez pas simplement INT_MAX plutôt que d'essayer de le faire vous-même? – WhozCraig

+0

Ok merci; cela est étrange. Je ne suis pas censé utiliser des constantes plus grandes qu'un octet pour cette tâche. – user3273046

Répondre

0

J'ai essayé mon code sur Linux 32 bits et là le problème particulier indiqué ci-dessus ne s'est pas produit.

Je conclus que le problème était dû au système d'exploitation et/ou au compilateur que j'utilisais. Comme je n'ai pas écrit les tests ou le makefile moi-même et que je ne suis pas assez familier avec C jusqu'à maintenant, je ne comprends toujours pas ce qui s'est mal passé.

Mais Pat a souligné (merci)

tirez-vous pour le débordement signé ou non? Toutes vos valeurs sont signées, mais vous ne cherchez apparemment qu'un carry-out du bit 31, qui n'est pas un débordement signé. -pat

l'algorithme que j'ai écrit a été cassé en premier lieu. J'ai eu la mauvaise idée du débordement dans mon esprit. J'ai dû vérifier le débordement signé qui se produit quand deux ints négatifs sont ajoutés et débordent à un positif ou deux nombres positifs à un négatif. (Selon l'arithmétique du complément à deux).

Si quelqu'un est intéressé ici est mon code de travail:

int addOK(int x, int y) { 
    int mask = 1 << 31; // 0x80000000 
    int msbX = mask & x; // Set all bit to 0 except sign bit 
    int msbY = mask & y; 
    int msbSum = mask & (x + y); 
    int prob1 = !(msbX^msbY); // == 1 iff x and y have the same sign - thats when an overflow may occur 
    int prob2 = !(msbX^msbSum); // == 0 iff x + y and x have a different sign - thats when an overfolow may occur 
    return (!prob1) | prob2;  // There is an overflow iff prob1 == 1 and prob2 == 0 
} 

Dans ce code, le problème j'ai demandé ci-dessus ne se produit même pas et je suis capable de l'exécuter directement sur mon Mac.