Promotions de type de données lors d’opérations arithmétiques: -1 <(unsinged int) 1 == false

main() { if ( -1 < (unsigned char) 1 ) printf("less than"); else printf("NOT less than"); } 

Imprime less than . Parce que (unsigned char) 1 est converti en (signed char) 1 puis: (signed) -1 < (signed) 1 , la sortie est donc less than .

Mais si je change le code ci-dessus en if ( (-1 < (unsigned int) 1 )

alors la sortie n’est NOT less than .

Il est donc évident que lorsque je change de caractère unsigned en unsigned int:

  • (signé) -1 est converti en unsigned int [c’est exactement ce qui se passe de l’autre côté]
  • puisque -1 est stocké en tant que complément à 2 de 1; le motif binary est évalué à 255 (probablement)
  • ainsi 255 <1 sera évalué à false et sinon, sera exécuté.
  • même si vous substituez int a = -1; à la place de ‘-1’ même résultat

Des questions:

  1. lors d’une arithmétique signée et non signée … comment être sûr si la signature sera convertie en non signée ou vice versa.

  2. pourquoi la conversion est-elle différente pour l’arithmétique entre unsigned char et char: apparemment non signé est converti en signé et unsigned int et int: apparemment signé est un convertisseur en non signé

PS: Je sais que cela ne dépend pas du compilateur, alors ne le dites pas.

Les règles sont les suivantes:

6.3.1.8 Conversions arithmétiques usuelles

Sinon, les promotions sur les entiers sont effectuées sur les deux opérandes. Ensuite, les règles suivantes sont appliquées aux opérandes promus:

  1. Si les deux opérandes ont le même type, aucune conversion supplémentaire n’est nécessaire.
  2. Sinon, si les deux opérandes ont des types entiers signés ou que les deux ont des types entiers non signés, l’opérande ayant le type de rang de conversion de nombre entier inférieur est converti en type de l’opérande avec le rang le plus élevé.
  3. Sinon, si l’opérande qui a un type entier non signé a un rang supérieur ou égal au rang du type de l’autre opérande, l’opérande avec le type entier signé est converti au type de l’opérande avec le type entier non signé.
  4. Sinon, si le type de l’opérande avec le type entier signé peut représenter toutes les valeurs du type de l’opérande avec le type entier non signé, l’opérande avec le type entier non signé est converti en type de l’opérande avec le type entier signé.
  5. Sinon, les deux opérandes sont convertis en un type entier non signé correspondant au type de l’opérande avec un type entier signé.

Les règles fonctionnent alors comme suit:

  • -1 < (unsigned char) 1

D'abord, les deux opérandes sont convertis en ints (car un int peut représenter toutes les valeurs de unsigned char). Ensuite, la comparaison est faite sur ces types signés. La règle 1 est alors utilisée. La comparaison réussit.

  • -1 < (unsigned int) 1

Un int ne pouvant pas représenter toutes les valeurs d'un unsigned int, la règle 3 est utilisée et l'entier signé est converti en un entier non signé (UINT_MAX - 1). La comparaison échoue maintenant.

Cela est dû aux promotions entières . Les deux arguments peuvent être représentés sous forme d’int, ils sont donc convertis en int.

ISO C 6.3.1.1, paragraphe 2:

Si un int peut représenter toutes les valeurs du type d’origine, la valeur est convertie en un int; sinon, il est converti en un unsigned int. Celles-ci sont appelées promotions d’entiers.48) Tous les autres types sont inchangés par les promotions d’entiers.