Réponse courte
Votre i
sera converti en un nombre entier non signé en ajoutant UINT_MAX + 1
l'addition sera effectuée avec les valeurs non signées, ce qui entraînera un grand nombre d'erreurs. result
(en fonction des valeurs de u
y i
).
Réponse longue
Selon la norme C99 :
6.3.1.8 Conversions arithmétiques habituelles
- Si les deux opérandes ont le même type, aucune autre conversion n'est nécessaire.
- Sinon, si les deux opérandes ont des types d'entiers signés ou si les deux ont des types d'entiers non signés, l'opérande ayant le type de rang de conversion d'entier le moins élevé est converti au type de l'opérande de rang le plus élevé.
- Sinon, si l'opérande de type entier non signé a un rang supérieur ou égal au rang du type de l'autre opérande, alors l'opérande de type entier signé est converti au type de l'opérande de type entier non signé.
- Sinon, si le type de l'opérande de type entier signé peut représenter toutes les valeurs du type de l'opérande de type entier non signé, alors l'opérande de type entier non signé est converti au type de l'opérande de type entier signé.
- Sinon, les deux opérandes sont convertis au type d'entier non signé correspondant au type de l'opérande de type entier signé.
Dans votre cas, nous avons un unsigned int ( u
) et les int signés ( i
). En se référant à (3) ci-dessus, puisque les deux opérandes ont le même rang, votre i
devra être converti en un nombre entier non signé.
6.3.1.3 Entiers signés et non signés
- Lorsqu'une valeur de type entier est convertie en un autre type entier autre que _Bool, si la valeur peut être représentée par le nouveau type, elle est inchangée.
- Sinon, si le nouveau type est non signé, la valeur est convertie en ajoutant ou en soustrayant de manière répétée une valeur de plus que la valeur maximale qui peut être représentée dans le nouveau type jusqu'à ce que la valeur soit dans la plage du nouveau type.
- Sinon, le nouveau type est signé et la valeur ne peut pas être représentée dans ce type ; soit le résultat est défini par l'implémentation, soit un signal défini par l'implémentation est levé.
Nous devons maintenant nous référer à (2) ci-dessus. Votre i
sera converti en une valeur non signée en ajoutant UINT_MAX + 1
. Le résultat dépendra donc de la façon dont UINT_MAX
est défini dans votre implémentation. Il sera grand, mais il ne débordera pas, car :
6.2.5 (9)
Un calcul impliquant des opérandes non signés ne peut jamais déborder, car un résultat qui ne peut pas être représenté par le type d'entier non signé résultant est réduit modulo le nombre qui est supérieur d'une unité à la plus grande valeur qui peut être représentée par le type résultant.
Bonus : Conversion arithmétique Semi-WTF
#include <stdio.h>
int main(void)
{
unsigned int plus_one = 1;
int minus_one = -1;
if(plus_one < minus_one)
printf("1 < -1");
else
printf("boring");
return 0;
}
Vous pouvez utiliser ce lien pour l'essayer en ligne : https://repl.it/repls/QuickWhimsicalBytes
Bonus : Effet secondaire de la conversion arithmétique
Des règles de conversion arithmétiques peuvent être utilisées pour obtenir la valeur de UINT_MAX
en initialisant une valeur non signée à -1
c'est-à-dire :
unsigned int umax = -1; // umax set to UINT_MAX
La portabilité est garantie, quelle que soit la représentation numérique signée du système, grâce aux règles de conversion décrites ci-dessus. Voir cette question SO pour plus d'informations : Est-il sûr d'utiliser -1 pour mettre tous les bits à vrai ?