2010-10-10 40 views
7
main() { 
    if (-1 < (unsigned char) 1) 
    printf("less than"); 
    else   
    printf("NOT less than"); 
} 

Imprime less than. Parce que, (unsigned char) 1est converti en(signed char) 1 et puis: (signed) -1 < (signed) 1, ainsi la sortie est less than.Promotion des types de données pendant les opérations arithmétiques: -1 <(uninged int) 1 == false

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

alors la sortie est NOT less than.

Il est donc évident que lorsque je change unsigned char unsigned int:

  • (signé) -1 est converti en unsigned int [exactement à l'opposé qui se passe]
  • depuis -1 est stocké en tant que complément de 2 de 1; le modèle binaire est évalué à 255 (probablement)
  • , donc 255 < 1 sera évalué à faux et sera exécuté.
  • même si vous remplacez int a = -1; à la place de « -1 » même résultat

Questions:

  1. pendant signé et non signé arithmétique ... comment être sûr que signé sera converti en non signé ou vice versa.

  2. pourquoi est conversion différent pour l'arithmétique entre unsigned char et le charbon: apparemment non signé est converti en signé et unsigned int et int: apparemment signé est convertisseur non signé

PS: Je sais que cela compilateur ne dépendants .. ne dites pas que c'est.

+0

ne sont pas tous des littéraux standard int? (unsigned char -> int promotion vs int -> unsigned int promotion) – flownt

Répondre

10

Les règles sont les suivantes:

6.3.1.8 habituelles conversions arithmétiques

...

Sinon, les promotions entières 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 autre conversion est nécessaire.
  2. Sinon, si les deux opérandes ont des types entiers signés ou si les deux ont des types entiers non signés, l'opérande ayant le type de rang de conversion entier inférieur est converti en type d'opérande de rang supérieur.
  3. Sinon, si l'opérande ayant un type entier non signé a un rang supérieur ou égal au rang du type de l'autre opérande, alors l'opérande avec un type entier signé est converti en type d'opérande avec un type entier non signé.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é, alors l'opérande avec le type entier non signé est converti en le type de l'opérande avec entier signé type.
  4. Sinon, les deux opérandes sont convertis en type entier non signé correspondant au type de l'opérande avec le 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 ensuite utilisée. La comparaison réussit.

  • -1 < (unsigned int) 1

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

+1

"rang"? qu'est-ce que cela implique? – bakra

+0

@bakra: Vous pouvez le considérer comme un "classement" des types. Un int long a un rang plus élevé qu'un char, par exemple. Voir 6.3.1.1 pour la définition officielle du rang. –

+1

@bakra: le "rang" d'un type intégral est défini ailleurs dans la norme C, mais l'essentiel est de savoir quel type a une plus grande plage de valeurs possibles, plus quelques exceptions. En particulier, "Le rang d'un type entier signé doit être supérieur au rang de tout type entier signé avec moins de précision." et "Le rang de tout type entier non signé doit être égal au rang du type entier signé correspondant, le cas échéant." – aschepler

1

Ceci est dû à promotions entières. Les deux arguments peuvent être représentés comme un 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 entier non signé. Ceux-ci sont appelés les promotions entières.48) Tous les autres types sont inchangés par les promotions entières.