Perché un int non firmato rispetto a un personaggio firmato risulta con un risultato inaspettato? [chiuso]

7

Perché il seguente codice emette y > x quando chiaramente 1 > -1?

unsigned x=1;
signed char y=-1;

if(x>y){
    printf("x>y");
}
else {
    printf("y>x");
}

Spiega questo risultato.

    
posta Sudhir 09.11.2012 - 11:38
fonte

3 risposte

10

La conversione del tipo implicito ti sta mordendo. Poiché x non è firmato, y viene convertito anche in unsigned; poiché -1 non si adatta a un carattere unsigned char, esso trabocca e diventa 255 (l'equivalente di char unsigned bit-bit di -1), che ovviamente è maggiore di -1.

    
risposta data 09.11.2012 - 11:50
fonte
2

La risposta di @tdammers è corretta, lasciami espandere un po '.

La rappresentazione binaria per i valori negativi presuppone che il bit più alto abbia il valore di 1 . Ad esempio, tutti i valori negativi a 8 bit assomigliano a 1xxx xxxx .

Il valore a 8 bit per -1 è 1111 1111 .

Quindi, lo stesso% binario% co_de per unsigned è 1111 1111 . Pertanto, lo stesso valore binario può essere interpretato in due modi diversi , a seconda che sia firmato o meno.

Nel tuo caso, come notato da @tdammers, la tua 255 è memorizzata nella variabile firmata , ma interpretata implicitamente come non firmata . Ovviamente, -1 , da cui il risultato.

P.S. Dovresti sempre controllare gli avvertimenti del compilatore. Tutti i compilatori moderni sollevano un avvertimento in merito.

    
risposta data 09.11.2012 - 12:47
fonte
1

Questo è un caso in cui si spera che si ottenga un avvertimento del compilatore sulla combinazione di un valore firmato e non firmato. Potrebbe essere ancora più specifico dove si parla di un lvalue senza segno e di un rvalore firmato.

Questo esempio sottolinea i rischi di C e in misura minore, il C ++ (che tende ad essere un po 'più severo riguardo al controllo dei tipi e che offre vari tipi di cast). Se vuoi scrivere codice C di buona qualità, diverse cose possono aiutarti:

  • Come precauzione di base, utilizza le opzioni del compilatore per generare gli avvisi più rigidi possibili.
  • In modo molto specifico, evitare la combinazione di valori firmati e non firmati nei confronti e nella maggior parte dei calcoli. (firmato = firmato * senza segno OK, firmato = firmato + senza segno OK, molti altri mixaggio, cattivo)
  • Usa printf (), trace () o ispezione delle variabili in un debugger per capire meglio dove vanno le cose. Se il tuo programma includesse una dichiarazione come printf ("x =% d, y =% d / n", x, y); vedresti che le cose sono andate male perché -1 è stato assegnato a y.
  • Studiare, studiare, studiare ... C è un linguaggio impegnativo e dovresti renderti il più esperto possibile sulla semantica e sugli effetti collaterali dei confronti e dei calcoli firmati e non firmati. È inoltre necessario un livello molto elevato di attenzione ai dettagli sull'intervallo di valori di input per le equazioni, il possibile intervallo di risultati di equazioni e se le costanti possono effettivamente adattarsi alle variabili a cui sono assegnate.
  • Se appropriato, utilizza tecniche di programmazione difensiva come le asserzioni per esporre problemi di programmazione durante lo sviluppo.
risposta data 09.11.2012 - 12:40
fonte

Leggi altre domande sui tag