2012-04-01 9 views
13

perché d non è uguale b in questo esempio?risultato di calcolo strano

unsigned int z = 176400; 
    long a = -4; 
    long b = a*z/1000; //b=4294261 
    long c = a*z; // c=-705600 
    long d = c/1000; // d =-705 

Uso Visual Studio 2008, Windows XP, core2duo. Grazie.

+6

... Perché d == c/1000. È una vita vera? – outis

+2

@crushanator Infatti, a non è uguale a d. Hai visto che? –

+3

Perché in questo esempio 1 non è uguale a 2: 'int a = 1; int b = 2; '? –

risposta

5

Sembra che si stia utilizzando una piattaforma in cui lo int e lo long hanno la stessa dimensione. (Ho dedotto questo per il fatto che se long era in grado di contenere tutti i valori validi di unsigned int che non avrebbe visto il comportamento che si sta vedendo.)

Ciò significa che nell'espressione a*z, sia a e z vengono convertiti in unsigned long e il risultato è di tipo unsigned long. (ISO/IEC 14882: 2011, 5 [expr]/9 ... "Altrimenti, entrambi gli operandi sono convertiti nel tipo intero senza segno corrispondente al tipo dell'operando di tipo intero con segno")

c è il risultato della conversione di questa espressione da unsigned long a long e nel tuo caso ciò comporta un risultato definito dall'implementazione (che sembra essere negativo) poiché il valore positivo di a*z non è rappresentabile in un long firmato. In c/1000, viene convertito in long e la divisione long viene eseguita (nessun gioco di parole previsto) risultante in un long (che risulta essere negativo) e viene memorizzato in d.

Nelle espressioni a*z/1000, 1000 (un'espressione del tipo int) viene convertito unsigned long e la divisione viene eseguita tra due unsigned long conseguente risultato positivo. Questo risultato è rappresentabile come long e il valore è invariato alla conversione in long e memorizzato in b.

+0

Questo è esattamente il caso del compilatore MS C. – Inisheer

+0

L'overflow firmato è un comportamento non definito, ma il modo. –

+1

@KerrekSB: Sì, ma in questo esempio non esiste overflow con segno. –