2010-04-16 13 views
6

Oggi ho trovato il seguente:Moltiplicando char e int insieme in C

#include <stdio.h> 

int main(){ 
char x = 255; 
int z = ((int)x)*2; 

printf("%d\n", z); //prints -2 

return 0; 

} 

Quindi, fondamentalmente sto ricevendo un overflow perché il limite di dimensione è determinata dalle operandi sul lato destro del segno = ??

Perché non trasmetterlo a int prima di moltiplicare il lavoro?

In questo caso sto utilizzando un carattere e int, ma se uso "long" e "long long int" (c99), ho un comportamento simile. È generalmente sconsigliato fare aritmetica con operandi di diverse dimensioni?

risposta

11

char può essere firmato o non firmato, a seconda del compilatore.

Nel tuo caso, sembra che sia firmato e 255 non rientra nell'intervallo che può rappresentare (probabilmente, può rappresentare solo numeri da -128 a 127).

Quindi il problema si verifica quando si assegna 255 alla variabile char - questo si traduce in un valore definito dall'implementazione, che nel tuo caso sembra essere -1.

Quando si moltiplica -1 per 2, si ottiene -2. Nessun mistero lì. Il cast a (int) non esegue nulla: i tipi più stretti di int vengono sempre promossi a int o unsigned int prima di eseguire qualsiasi calcolo con essi.

4

No, non si ottiene un overflow sulla seconda riga (moltiplicazione). Il problema è che il compilatore usa signed char per impostazione predefinita e 255 overflow e significa -1. Fondamentalmente, stai inizializzando la variabile x con il valore di -1. La conversione da -1 a int si tradurrà in -1 (signed gli operandi otterranno l'estensione del segno negli upcast, mentre gli operandi unsigned avranno estensione zero).

è possibile forzare il char di essere unsigned aggiungendo il prefisso unsigned:

unsigned char x = 255; 
5

Sembra che char è firmato sulla vostra piattaforma. Quindi lo char x = 255 è lo stesso di char x = -1. Il cast di int non ha importanza.

provare a cambiare quello a:

unsigned char x = 255; 
3

Le altre risposte spiegano bene come il tuo esempio "funziona", quindi non lo spiegherò più.

Tuttavia, mi permetta di osservare che, se ciò che si desidera utilizzare è un "unsigned 8 bit integer", basta usare <stdint.h> s' uint8_t già (e le sue 16, 32, compagni a 64 bit) e tenere lontano da tutti i char s , short se int s in questo mondo.

+1

#include per questi tipi. – slartibartfast