Il linguaggio C esegue le "conversioni aritmetiche usuali" per molti operatori - il le conversioni sono delineate in 6.3.1.8 dello standard C99. Per gli operandi integrali, vengono eseguite le prime promozioni e questo è ciò che sta causando il problema. Le promozioni sono illustrate nel 6.3.1.1 (aritmetiche operandi/booleani, caratteri e numeri interi), che dice tra l'altro:
Se un int può rappresentare tutti i valori del tipo di originale, il valore viene convertito in un int; in caso contrario, viene convertito in un int unsigned. Queste sono chiamate promozioni intere. Tutti gli altri tipi sono invariati dalle promozioni intere.
Le promozioni sono applicati solo a oggetti o espressioni con un tipo intero con un rango inferiore int
e unsigned int
(o bitfields).
Quindi nel tuo Exression:
t1 < t2-1
anche se le variabili sono unsigned short
sono promossi a int, dal momento che sulla vostra piattaforma int
può rappresentare tutti i valori di unsigned short
. Pertanto, l'espressione viene valutata utilizzando i tipi int
e non si verifica un underflow: la parte dell'espressione t2-1
termina come 1 negativo.
Nell'espressione:
s1 < s2-1
i tipi unsigned long
non vengono promossi, perché hanno un più alto 'rango' di int
/unsigned int
, quindi l'espressione viene valutata utilizzando l'aritmetica non firmato (con l'underflow dal sottrazione), e il s2-1
sottoespressione restituisce un numero molto grande, non negativo 1.
come litb indicato in un commento, se la piattaforma avesse int
implementato come un tipo a 16 bit (che è consentito - MS-DOS per esempio), il pro movimento di unsigned short
invece di unsigned int
anziché int
, poiché un int
non è in grado di rappresentare tutti i valori di unsigned short
(unsigned short
deve essere di almeno 16 bit). In tal caso, entrambe le istruzioni if
verrebbero considerate true.
fonte
2009-09-13 09:50:22
~ nairboon: spero che non ti dispiaccia la modifica. Il codice che ho sostituito con il tuo è funzionalmente lo stesso, ma può essere copiato/incollato in un editor e compilato senza modifiche. –
Si noti che questo risultato non è garantito come risultato. Sulle macchine in cui int memorizza lo stesso intervallo di valori più breve (credo che le macchine a 16 bit, penso), vedrete l'output per entrambi i se, perché la promozione verrà convertita in unsigned int, anziché in int. –