C ++ Aritmetico con tipi integrali misti che provoca overflow
-
21-12-2019 - |
Domanda
Ho fatto alcuni test in VC ++ 2010 Operandi di miscelazione di diverse dimensioni che causano il trabocco nell'operazione Aggiungi:
int _tmain(int argc, _TCHAR* argv[])
{
__int8 a=127;
__int8 b=1;
__int16 c=b+a;
__int8 d=b+a;
printf("c=%d,d=%d\n",c,d);
return 0;
}
//result is: c=128, d=-128
.
Non capisco perché c== 128!La mia comprensione è che in entrambe le aggiunte, B + A sono ancora considerate aggiunte di 2 variabili 8 bit firmate.Quindi il risultato è un troppopieno I.e. -128. Dopo di questo , il risultato viene quindi promosso a 16 bit firmato INT per il primo funzionamento di assegnazione e c dovrebbe ancora ottenere un valore 16 bit -128.La mia comprensione è corretta?Lo standard C ++ è un po 'difficile da leggere.Il capitolo 4 sembra parlare di promozione integerale ma non riesco a trovare nulla di relativo a questo esempio specifico.
Soluzione
.La mia comprensione è che in entrambe le aggiunte, B + A sono ancora considerate aggiunte di 2 variabili a 8 bit firmate.Quindi il risultato è un troppopieno I.e. -128.
No, la promozione avviene prima che venga valutato il +
, non dopo.L'aggiunta avviene quando sia a
che b
sono positive.Entrambi i numeri sono promossi a int
s per un'aggiunta, aggiunto come due numeri positivi e quindi convertiti in un breve 16 bit.A nessun punto del processo il risultato diventa negativo a causa di un troppopieno, quindi il risultato finale di 128.
Probabilmente, questo ha senso: il comportamento di a
e b
corrisponde a quello di due numeri in matematica, rendendolo più intuitivo per i professionisti della lingua.
Altri suggerimenti
è la promozione integrale.
.1 A PRVALUE di un tipo intero diverso da BOOL, CHAR16_T, CHAR32_T o WCHAR_T il cui grado di conversione integro (4.13) è inferiore al grado di int può essere convertito in un prvalo di tipo intSe int può rappresentare tutti i valori del tipo di origine;In caso contrario, la prvalue sorgente può essere convertita in una prvalue di tipo int non firmato.[§ 4.5]
in questa dichiarazione
__int16 c=b+a;
.
.Innanzitutto, tutti i valori
char
eshort int
vengono automaticamente elevati aint
.Questo processo è chiamato Promozione integrale .Successivamente, tutti gli operandi vengono convertiti fino al tipo di operando più grande, che si chiama Promozione tipo .[Herbert Schildt]
I valori delle variabili b
e a
verranno promossi a int
e quindi l'operazione si applica su di essi.
Nella rappresentazione intera intera complementare TWOS, un valore firmato è rappresentato impostando il bit più alto. Ciò consente alla macchina di aggiungere e sottrarre interi binari con le stesse istruzioni, indipendentemente dal fatto che il numero intero sia firmato.
a = 127 == 0x7F == 0b01111111
+ b = 1 == 0x01 == 0b00000001
-------------------------------
c = 128 == 0x80 == 0b10000000
d =-128 == 0x80 == 0b10000000
.
Le variabili c
e d
possono avere tipi diversi, ma diversi tipi di numeri interi sono semplicemente interpretazioni diverse di un singolo valore binario. Come puoi vedere sopra, il valore binario si adatta solo a 8 bit. Poiché lo standard richiede termini di un'espressione matematica per essere zero- o segno esteso (promosso) alla dimensione di una parola macchina prima qualsiasi matematica è fatto e né l'operando sarà esteso-esteso, il risultato è sempre 0b10000000
, indipendentemente dal tipo degli operandi.
In sintesi, la differenza tra i risultati è che, a un numero intero a 16 bit il bit del segno è 0b1000000000000000
(che a+b
non ha), e su un numero intero a 8 bit il bit del segno è 0b10000000
) .