Question

Voir cet extrait de code

int main()
{ 
 unsigned int a = 1000;
 int b = -1;
 if (a>b) printf("A is BIG! %d\n", a-b);
 else printf("a is SMALL! %d\n", a-b); 
 return 0;
}   

Cela donne la sortie: un est petit: 1001

Je ne comprends pas ce qui se passe ici. Comment le travail de l'opérateur> ici? Pourquoi est « un » plus petit que « b »? S'il est en effet plus petit, pourquoi dois-je obtenir un nombre positif (1001) comme la différence?

Était-ce utile?

La solution

Les opérations binaires entre les différents types entiers sont effectués dans un type « commun » défini par ce qu'on appelle conversions arithmétiques habituelles (voir la spécification du langage, 6.3.1.8). Dans votre cas, le type « commun » est unsigned int. Cela signifie que opérande int (votre b) va se convertir à unsigned int avant la comparaison, ainsi que dans le but d'effectuer la soustraction.

Lorsque -1 est converti en unsigned int le résultat est la valeur possible unsigned int maximale (comme UINT_MAX). Inutile de dire que cela va être supérieure à la valeur de votre 1000 non signé, ce qui signifie que a > b est en effet faux et a est en effet petit par rapport à (unsigned) b. Le if dans votre code devrait se résoudre à else branche, qui est ce que vous avez observé dans votre expérience.

Les mêmes règles de conversion applicables à la soustraction. Votre a-b est vraiment interprété comme a - (unsigned) b et le résultat a le type unsigned int. Cette valeur ne peut pas être imprimé avec spécificateur format %d, puisque %d fonctionne uniquement avec des valeurs signé . Votre tentative d'imprimer avec des résultats %d dans un comportement non défini, la valeur que vous voyez imprimé (même si elle a une explication déterministe logique dans la pratique) est complètement dénuée de sens du point de vue du langage C.

Modifier En fait, je peux me tromper au sujet de la part du comportement non défini. Selon la spécification du langage C, la partie commune de la plage du type entier correspondant signée et non signée est une représentation identique (ce qui implique, selon la référence 31, « interchangeabilité comme arguments aux fonctions »). Ainsi, le résultat de l'expression a - b est 1001 non signé comme décrit ci-dessus, et à moins que je me manque quelque chose, il est légal d'imprimer cette valeur non signée spécifique avec spécificateur %d, car il se situe dans la plage positive de int. Impression (unsigned) INT_MAX + 1 avec %d serait indéterminée, mais 1001u est très bien.

Autres conseils

Sur une mise en œuvre typique où int est 32 bits, -1 lorsqu'il est converti en un unsigned int est 4294967295, qui est en effet ≥ 1000.

Même si vous traitez la soustraction dans un monde unsigned, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001 qui est ce que vous obtenez.

Voilà pourquoi gcc va cracher un avertissement lorsque vous comparez avec unsigned signed. (Si vous ne voyez pas un avertissement, passer le drapeau -Wsign-compare.)

Vous faites des comparaisons non signé, à savoir l'on compare 1000-2 ^ 32 -. 1

La sortie est signée en raison de% d dans printf.

N.B.. parfois le comportement lorsque vous mélangez signé et opérandes non signé est spécifique au compilateur. Je pense qu'il est préférable de les éviter et ne jette dans le doute.

Trouver un moyen facile de comparer, peut-être utile lorsque vous ne pouvez pas vous débarrasser de la déclaration non signée, (par exemple, [NSArray compte]), juste forcer le « unsigned int » à un « int ».

S'il vous plaît me corriger si je me trompe.

if (((int)a)>b) {
    ....
}

Le matériel est conçu pour comparer signé et signé non signé non signé.

Si vous voulez que le résultat arithmétique, convertir la valeur non signée à un plus grand type signé en premier. Sinon, le compilateur wil suppose que la comparaison est vraiment entre les valeurs non signées.

-1 est représenté comme 1111..1111, donc une très grande quantité ... Le plus grand ... Quand interprété comme non signé.

 #include<stdio.h>
 int main()
 {
   int a = 1000;
   signed int b = -1, c = -2;
   printf("%d",(unsigned int)b);
   printf("%d\n",(unsigned int)c);
   printf("%d\n",(unsigned int)a);

   if(1000>-1){
      printf("\ntrue");
   }
   else 
     printf("\nfalse");
     return 0;
 }

Pour cela, vous devez comprendre la priorité des opérateurs

  1. Opérateurs Relational fonctionne de gauche à droite ... alors quand vient

    if (1000> -1)

puis d'abord, il changera -1 à entier non signé parce que int est par défaut traité comme numéro non signé et plage il supérieur au nombre signé

-1 changera dans le nombre non signé, il se transforme en un très grand nombre

en comparant a> b où a est de type unsigned int et b est de type int, b est type sur coulé à unsigned int so, signée valeur int -1 est convertie en valeur MAX de unsigned ** (de 0 à (2 ^ 32) -1) ** Ainsi, a> b à savoir, (1000> 4294967296) devient fausse. Par conséquent boucle d'autre printf ( "a est SMALL% d \ n", a-b);. exécuté

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top