2010-04-16 10 views
6

Hoy he encontrado lo siguiente:carbón y int juntos en C

#include <stdio.h> 

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

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

return 0; 

} 

Así que básicamente me estoy haciendo un desbordamiento debido a que el límite de tamaño está determinado por los operandos en la parte derecha del signo = ??

¿Por qué no convertirlo a int antes de multiplicar el trabajo?

En este caso estoy usando un char y int, pero si uso "long" y "long long int" (c99), entonces obtengo un comportamiento similar. ¿Se aconseja generalmente no hacer aritmética con operandos de diferentes tamaños?

Respuesta

11

char puede ser ya sea con o sin signo, dependiendo de su compilador.

En su caso, parece estar firmado, y 255 está fuera del rango que puede representar (es probable que solo represente números de -128 a 127).

Entonces, el problema ocurre cuando asigna 255 a su variable char - esto da como resultado un valor definido por la implementación, que en su caso, parece ser -1.

Cuando multiplicas -1 por 2, obtienes -2. No hay misterio allí. El lanzamiento a (int) no hace nada - los tipos más estrechos que int siempre se promueven a int o unsigned int antes de realizar cualquier cálculo con ellos.

4

No, no recibirá un desbordamiento en la segunda línea (multiplicación). El problema es que su compilador usa signed char de manera predeterminada y 255 desbordamientos y significará -1. Básicamente, está inicializando la variable x con el valor de -1. La conversión de -1 a int dará como resultado -1 (signed los operandos recibirán extensión de signo en las actualizaciones, mientras que los operandos unsigned tendrán extensión cero).

puede forzar la char para ser unsigned añadiendo el prefijo unsigned:

unsigned char x = 255; 
5

Parece que Char se firmó en su plataforma. Entonces, el char x = 255 es efectivamente el mismo que char x = -1. El lanzamiento a int no importa.

que trate de cambiar a:

unsigned char x = 255; 
3

Las otras respuestas explican muy bien cómo funciona su ejemplo, por lo que no voy a explicar eso de nuevo.

Sin embargo, permítanme observar que si lo que desea utilizar es un "entero sin signo de 8 bits", sólo tiene que utilizar <stdint.h> 's uint8_t ya (y sus 16, 32, compañeros de 64 bits) y mantenerse alejado de todos los char s , short sy int s en este mundo.

+1

#include para estos tipos. – slartibartfast