2017-09-12 6 views
2

Je viens exécuter le code suivantdifférents types de données - signés et non signés

main() 
{ 
    char a = 0xfb; 
    unsigned char b = 0xfb; 
    printf("a=%c,b=%c",a,b); 
    if(a==b) { 
    printf("\nSame"); 
    } 
    else { 
    printf("\nNot Same"); 
    } 
} 

Pour ce code, je suis la réponse que

a =? b =?

différents

Pourquoi ne pas obtenir le même, et quelle est la valeur a et b?

+1

lire un bon livre C et en apprendre davantage sur la représentation de la mémoire des différents types de données et de la différence entre '' signed' et les types de données unsigned' – krpra

+3

« * différent * » vraiment? – alk

+0

"quelle est la valeur pour a et b" aurait pu être étudié facilement avec 'printf ("a =% d, b =% d", a, b);' – chux

Répondre

4

Il y a 2 cas à considérer:

  • si le type char est non signé par défaut, à la fois a et b prennent la valeur 251 et le programme imprimera Same.
  • si le type char est signé par défaut, ce qui est hélas le cas le plus courant, la définition char a = 0xfb; a un comportement défini de mise en œuvre 0xfb (251 en décimal) est probablement hors de portée pour le type char (généralement -128 à 127). Probablement la valeur -5 sera stockée dans a et a == b évalue à 0 comme les deux arguments sont promus à int avant la comparaison, par conséquent -5 == 251 sera faux.

Le comportement de printf("a=%c,b=%c", a, b); est également dépendant du système que les caractères non ASCII -5 et 251 peut imprimer de manière inattendue le cas échéant. Notez cependant que les deux imprimeront le même que le format %c spécifie que l'argument est converti en unsigned char avant l'impression. Il serait plus sûr et plus explicite d'essayer printf("a=%d, b=%d\n", a, b);

Avec gcc ou clang, vous pouvez essayer de recompiler votre programme avec -funsigned-char pour voir comment le comportement sera différent.

+0

La meilleure réponse dans la mesure où elle traite de 'a = 0xfb;' a un comportement défini par l'implémentation. – chux

6

La ligne if (a == b) ... fait la promotion des caractères en entiers avant la comparaison, de sorte que la signature du caractère affecte la façon dont cela se produit. Le caractère non signé 0xFB devient l'entier 251; le caractère signé 0xFB devient l'entier -5. Ainsi, ils sont inégaux.

+0

Le caractère signé est devenu -5 avant 'si (a == b) ', mais à' char a = 0xfb; 'heure. – chux

+0

D'une certaine manière, oui. Le seul octet 0xFB est correctement interprété comme -5 même s'il est stocké dans un octet. C'est pourquoi, une fois la promotion terminée, elle est physiquement étendue à 0xFFFFFFFB, tandis que l'autre est physiquement étendue à 0x000000FB. –

+0

* C'est pourquoi, une fois la promotion terminée, il est physiquement étendu à 0xFFFFFFFB * peut-être, peut-être pas. Le comportement ne dépend pas de la taille de 'int' ni de la représentation des entiers en mémoire. Stocker '0xfb' dans un' char' 8 bits signé a un comportement défini par l'implémentation, ce qui dans la plupart des architectures actuelles signifiera stocker '-5', le reste est entièrement défini sur toutes les architectures. – chqrlie

0

char magasins de -128 à 127 et unsigned char magasins de 0 à 255. et 0xfb représente 251 en décimal qui est au-delà de la limite de char a.

2

Selon le C standard (6.5.9 opérateurs) l'égalité

4 Si les deux opérandes sont de type arithmétique, l'arithmétique conversions habituelles sont effectuées ....

Les conversions arithmétiques habituelles incluent les promotions d'entier.

De la norme C (6.3.1.1 booléens, les caractères et des nombres entiers)

2 Les suivants peuvent être utilisés dans une expression où on peut utiliser une ou int unsigned int: ...

Si un int peut représenter toutes les valeurs de le type d'origine (limité par la largeur, pour un champ de bits), la valeur est convertie en int; sinon, il est converti en un entier non signé. On les appelle les promotions entières 0,58) Tous les autres types ne sont pas modifiées par l'entier promotions.

Ainsi, dans cette expression de l'égalité

a == b 

les deux opérandes sont convertis en type int. L'opérande signé (à condition que le type char se comporte comme le type signed char) est converti en le type int au moyen de propager le bit de signe.

Comme résultat opérandes ont des valeurs différentes en raison de la différence dans la représentation binaire.

Si le type char se comporte comme le type unsigned char (par exemple en définissant une option correspondante du compilateur) alors évidemment les opérandes seront égaux.

+0

* Il en résulte que les opérandes ont des valeurs différentes dues à la différence de la représentation binaire. * Plus précisément à cause de la différence d'interprétation de la représentation binaire. – chqrlie