Jouons avec les unsigned int en C
Mixer des entiers signés (int
) et non signés (unsigned int
) en C ou C++ est une bonne manière de se tirer dans le pied…
Petite démonstration :
[c]
#include <stdio.h>
int main()
{
int ref = -6;
int a = 4;
unsigned int b = 4;
int x = 0;
unsigned int y = 0;
if (ref + a == ref + b)
printf("ref + a == ref + b\
");
printf("ref + a = 0x%x\
", ref + a);
printf("ref + b = 0x%x\
", ref + b);
if (ref + a > x)
printf("ref + a > x\
");
if (ref + b > x)
printf("ref + b > x\
");
if (ref + a > y)
printf("ref + a > y\
");
if (ref + b > y)
printf("ref + b > y\
");
if (ref + a > 0)
printf("ref + a > 0\
");
if (ref + b > 0)
printf("ref + b > 0\
");
}
Enregistrons le tout dans un fichier nommé test.c
, puis compilons avec la commande suivante :
$ g++ -Wall -Wextra test.c -o test
test.c: In function ‘int main()':
test.c:12: attention : comparaison entre des expressions entières signée et non signée
test.c:20: attention : comparaison entre des expressions entières signée et non signée
test.c:23: attention : comparaison entre des expressions entières signée et non signée
Notons les jolis avertissements qui s’affichent pour les lignes 12, 20 et 23 et testons maintenant l’exécution :
$ ./test
ref + a == ref + b
ref + a = 0xfffffffe
ref + b = 0xfffffffe
ref + b > x
ref + a > y
ref + b > y
ref + b > 0
Le test (ref + a == ref + b) retourne vrai, et en effet, comme on peut le voir en dessous, la représentation binaire (ici en hexadécimale) est identique dans les 2 cas. Tous les autres tests auraient dû échouer : -6 + 4 == -2, ce qui est inférieur à 0. On est tous d’accord ;)
Et pourtant, à chaque fois qu’un entier non signé était présent dans l’expression evaluée, le résultat s’explique mais est pour le moins surprenant. 4 résultats surprenants, mais seulement 2 avertissements correspondants…
Bon débuggage…
PS : l’avertissement à la ligne 12 concerne l’évaluation de ref + a == ref + b
.