Domanda

Vedi questo frammento di codice

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;
}   

Questo dà l'output:a è PICCOLO:1001

Non capisco cosa sta succedendo qui.Come funziona l'operatore > qui?Perché "a" è più piccola di "b"?Se è effettivamente più piccolo, perché ottengo un numero positivo (1001) come differenza?

È stato utile?

Soluzione

operazioni binarie tra diversi tipi integrali vengono eseguite all'interno di un tipo "comune" definito dai cosiddetti conversioni aritmetiche abituali (vedere la specifica del linguaggio, 6.3.1.8). Nel tuo caso il tipo "comune" è unsigned int. Ciò significa che int operando (il vostro b) otterrà convertito unsigned int prima del confronto, così come per l'esercizio di una sottrazione.

Quando -1 viene convertito unsigned int il risultato è il valore massimo possibile unsigned int (uguale UINT_MAX). Inutile dire, che sta per essere maggiore di vostro valore 1000 senza segno, il che significa che a > b è davvero falso e a è davvero piccolo rispetto al (unsigned) b. Il if nel codice dovrebbe risolvere a else ramo, che è quello che avete osservato nell'esperimento.

Le stesse regole di conversione valgono per sottrazione. Il tuo a-b è davvero interpretato come a - (unsigned) b e il risultato è di tipo unsigned int. Tale valore non può essere stampata con il formato %d identificatore, dal momento che %d funziona solo con firmato valori. Il tentativo di stampare con risultati %d in un comportamento indefinito, in modo che il valore che si vede stampato (anche se ha una spiegazione logica deterministica in pratica) è del tutto priva di senso dal punto di vista del linguaggio C.

Modifica In realtà, potrei sbagliarmi circa la parte comportamento non definito. Secondo specifica del linguaggio C, la parte comune della gamma del corrispondente firmata e senza segno tipo integer avranno rappresentazione identica (che implica, secondo la nota 31, "intercambiabilità come argomenti a funzioni"). Quindi, il risultato dell'espressione a - b è 1001 unsigned come descritto sopra, ed a meno che non mi manca qualcosa, è legale per stampare questo valore senza segno specifico con %d specificatore, dal momento che rientra nel range positivo di int. Stampa (unsigned) INT_MAX + 1 con %d sarebbe indefinito, ma 1001u va bene.

Altri suggerimenti

In una tipica implementazione dove int è 32 bit, -1 quando convertito in un unsigned int è 4294967295 che è effettivamente ≥ 1000.

Anche se si trattano la sottrazione in un mondo unsigned, 1000 - (4,294,967,295) = -4,294,966,295 = 1,001 che è quello che si ottiene.

Ecco perché gcc sputerà un messaggio di avviso quando si confronta con unsigned signed. (Se non vedi un messaggio di avviso, passare il flag -Wsign-compare.)

Si sta facendo il confronto senza segno, vale a dire il confronto 1000-2 ^ 32 -. 1

L'uscita è firmato a causa di% d in printf.

NB. a volte il comportamento quando si mescolano firmati e non firmati operandi è specifica del compilatore. Penso che sia meglio evitare di loro e fare calchi in caso di dubbio.

Trovare un modo semplice per confrontare, forse utile quando non è possibile sbarazzarsi della dichiarazione non firmata, (ad esempio, [count NSArray]), basta forzare la "unsigned int" ad un "int".

Si prega di correggermi se sbaglio.

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

L'hardware è progettato per confrontare firmato per firmato e non firmato a unsigned.

Se si desidera che il risultato aritmetico, convertire il valore senza segno a un tipo firmato più grande prima. In caso contrario, il compilatore wil supporre che il confronto è davvero tra i valori senza segno.

E -1 è rappresentato come 1111..1111, quindi è una grande quantità ... Il più grande ... Quando interpretato come segno.

 #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;
 }

Per questo è necessario comprendere la precedenza degli operatori

  1. Gli operatori relazionali lavorano da sinistra a destra...quindi quando arriverà

    se(1000>-1)

quindi prima di tutto cambierà -1 in intero senza segno perché int è trattato per impostazione predefinita come numero senza segno e lo estende maggiore del numero con segno

-1 diventerà un numero senza segno, diventerà un numero molto grande

confrontando a> b dove a è unsigned tipo e b int è di tipo int, b viene colato tipo unsigned int così, firmato int valore -1 viene convertito in valore MAX senza segno ** (range: 0 a (2 ^ 32) -1) ** Così, a> b cioè, (1000> 4294967296) diventa falso. Quindi altro ciclo printf ( "un è SMALL% d \ n", a-b). eseguito

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top