En C, la conversion automatique des types fonctionne selon le principe des "usages arithmétiques habituels". Lorsqu'un opérande signé et un opérande non signé sont impliqués dans une expression, les règles de conversion suivantes s'appliquent :
Exemple de programmation dangereuse :
int a = -1; // signé unsigned int b = 1; printf("%d\n", a < b); // toujours faux, car a est converti en un très grand unsigned
Le résultat : -1, lorsqu'il est converti en unsigned, devient un nombre positif très grand.
Ce qu'il est important de retenir :
Question : Quel résultat l'expression (int)(unsigned)-1 renverra-t-elle ?
Réponse attendue incorrecte : "-1, car -1 doit être converti en int."
Réponse correcte :
Dans l'expression (unsigned)-1, -1 est d'abord converti en unsigned (sur une plate-forme 32 bits, cela correspond à 0xFFFFFFFF), puis à nouveau en signed int, ce qui dépend également de l'implémentation, mais souvent cela donnera à nouveau -1 (si l'on utilise le complément à 2). Cependant, il est plus précis de dire : Le résultat dépend des normes de représentation des nombres signés, mais dans la plupart des implémentations, cela donnera -1.
Exemple :
int x = (int)(unsigned)-1; // x == -1 sur la plupart des plates-formes
Histoire
Dans un gestionnaire de chaînes, une fonction de comparaison de taille était utilisée : si la longueur de la chaîne pouvait être négative, le programme signalait une erreur. Cependant, la longueur était de type size_t (non signé), et la comparaison avec
if(length < 0)retourne toujours faux, ce qui a conduit à une boucle infinie et à un débordement de mémoire.
Histoire
Lors de l'analyse des protocoles, les paquets réseau contenaient des champs non signés, tandis que les variables locales étaient signées. En raison du débordement des non signés lors du traitement de certaines valeurs, des calculs incorrects de la longueur des paquets se sont produits, ce qui a conduit à une vulnérabilité de débordement de tampon.
Histoire
Le module de comparaison de dates dans les journaux stockait la date en tant qu'unsigned int, mais cherchait à vérifier un intervalle de dates en int. Certaines valeurs limites, au lieu de déclencher l'exception attendue, ont conduit à un filtrage incorrect des enregistrements et à la perte de journaux importants.