2013-08-16 13 views
8

ho:convertire int a breve in C

int a = 2147483647; 
short b = (short)a; 

e ottengo b = -1 mentre mi aspetto int32 per essere convertito in int16 (short). Mi aspetto di vedere qualche valore e non-1.

Per favore qualcuno mi aiuti con questo.

+1

Direi che il valore non si adatta, quindi i risultati non sono definiti. –

+2

'-1' * è *" qualche valore ". E il cast '(breve)' non è necessario; la conversione verrà eseguita implicitamente: 'short b = a;' –

+2

@BartFriederichs: il risultato della conversione è * definito dall'implementazione *, non indefinito. –

risposta

3

Il tuo int A è più grande della dimensione del corto. Quando converti A in short, ottieni un 1 nel bit più a sinistra, che sta per indicare che si tratta di un numero negativo. Dato che stai ricevendo -1, suppongo che stai ricevendo 1s in tutti i 16 bit, che ti darà -2^15 + 2^14 + 2^13 ... + 2^0, che ti darà -1. In breve (nessun gioco di parole previsto), non è possibile convertire il numero intero in un corto se è troppo grande.

17

Il valore 2147483647 o 2 -1 sovrascrive un numero intero a 16 bit. La sua rappresentazione binaria è zero nel MSB seguito da 31 nei bit rimanenti.

Sembra che nella vostra implementazione gli ultimi 16 bit siano stati presi nella conversione in short. Quando questo accade, tutti sono impostati 1, conseguente 2's complement rappresentazione di -1:

32-bit int: 01111111111111111111111111111111 
16-bit short: ----------------1111111111111111 

Tuttavia, né la rappresentazione 2-complemento né questo comportamento in generale è parte dello standard C++, così questo comportamento è definito dall'implementazione.

+7

@EricPostpischil: il comportamento non è indefinito; il risultato è definito dall'implementazione, il che significa che l'implementazione deve documentarlo. –

+2

@EricPostpischil: n3690 pagina 80 4.7 (1) dice che è stata definita l'implementazione, non indefinita. Non sono sicuro che un'implementazione sia libera di definire un comportamento indefinito, tuttavia :-) – 6502

6

Questo è implementation defined comportamento, per esempio gccIntegers Implementation document dice:

Per la conversione a un tipo di larghezza N, il valore è ridotto modulo 2^N per essere entro il raggio del tipo; nessun segnale è alzato.

Questo può essere diverso dal compilatore a compilatore, io non sono in grado di scavare documenti analoghi per clangvisual studio.

Dalla bozza di standard C++, sezione 4.7 Integral conversions comma 3:

Se il tipo di destinazione è firmato, il valore è invariato se può essere rappresentato nel tipo di destinazione (e bit-field larghezza); in caso contrario, il valore è definito dall'implementazione.

Se questo è stato unsigned allora si sarebbe perfettamente comportamento definito, di cui al comma 2:

Se il tipo di destinazione non è firmato, il valore risultante è il minimo intero senza segno congruente al numero intero fonte (modulo 2n dove n è il numero di bit usati per rappresentare il tipo senza segno). [Nota: nella rappresentazione a complemento a due, questa conversione è concettuale e non vi è alcun cambiamento nel modello di bit (se non vi è alcun troncamento).-end note]

La lingua è simile nella sezione standard C996.3.1.3 Signed and unsigned integers.

9

Conversione di un valore di un firmato tipo, quando il valore di origine non rientra nel tipo di destinazione, resa un'implementazione definito risultato . Ciò significa che qualsiasi documentazione conforme del compilatore deve documentare quale sia il risultato.

(Questo è diverso il comportamento in caso di overflow di un operatore aritmetico. Ad esempio:

int overflow = INT_MAX + 1; 

in realtà ha comportamento indefinito Ma in entrambi i casi, si deve fare attenzione a scrivere il codice in modo che doesn. innescano questo tipo di problema)

Per molte implementazioni, sia per la conversione che per l'aritmetica, un overflow in cui il target è un tipo N-bit prende semplicemente N bit di basso ordine del risultato corretto.

Nel tuo caso, apparentemente int è di 32 bit e short è di 16 bit (quelle dimensioni possono variare su diverse implementazioni). 2147483647 è 0x7fffffff, i 16 bit di basso ordine sono 0xffff, che è (ancora una volta sulla tua implementazione) la rappresentazione di -1 nel tipo short.

Per la conversione in tipi senza segno, il risultato è rigorosamente definito dallo standard; prende i bit N di basso ordine del risultato. E per il traboccamento della conversione in virgola mobile (ad esempio, la conversione di un valore molto grande double in float), il comportamento non è definito.

Finora, questo è lo stesso per C e C++. Ma solo per aggiungere confusione, a partire dallo standard del 1999 una conversione firmata straripante è consentita per innalzare un segnale definito dall'implementazione. Il C++ non ha questo. Non conosco alcun compilatore che lo faccia effettivamente.

mi aspetto di vedere un certo valore e non -1.

-1è "un certo valore". C'era qualche valore specifico che ti aspettavi?

Per inciso:

short b = (short)a; 

Il cast non è necessaria. Assegnazione, inizializzazione, passaggio parametri e istruzioni return possono assegnare valori tra qualsiasi tipo numerico senza cast. Il valore viene convertito implicitamente:

short b = a; 
3

Si può fare questo:

uint32_t sum=0xFFFF1234; 
uint16_t *p= (uint16_t *) ∑ 
uint16_t checksum=p[0]; 

check-sum è 0x1234.

Ecco un altro modo:

union ToShort 
{ 
     uint32_t sum; 
     uint16_t checksum[2]; 
} toShort; 
toShort.sum=0xFFFF1234; 
cout << hex << toShort.checksum[0]; 

uscita è 1234.