Multiplicando Char y int juntos en C
Pregunta
Hoy me encontré con lo siguiente:
#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 poniendo 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 se convierte para int antes de multiplicar el trabajo?
En este caso estoy usando un char e int, pero si uso "largo" y "long long int" (C99), entonces consigo un comportamiento similar. Es por lo general desaconsejó hacer aritmética con operandos de diferentes tamaños?
Solución
char
puede ser ya sea con o sin signo, dependiendo de su compilador.
En su caso, parece que está firmado, y 255 está fuera del rango que puede representar (probablemente, sólo puede representar números a partir de -128 a 127).
Así que el problema se produce cuando se asigna a la variable de 255 char
-. Esto se traduce en un valor definido por la implementación, que en su caso, parece ser -1
Si se multiplica por -1 2, se obtiene -2. No hay misterio. El reparto de (int)
no hace nada -. int
tipos más estrechos que siempre son promovidos a int
o unsigned int
antes de que los cálculos se hacen con ellos
Otros consejos
Parece que Char se firmó en su plataforma. Por lo que el char x = 255
es efectivamente el mismo que char x = -1
. El reparto de int no importa.
Trate de cambiar eso a:
unsigned char x = 255;
No, no están recibiendo un desbordamiento en la segunda línea (multiplicación). El problema es que el compilador está utilizando signed char
por desbordamientos por defecto y 255 y significará -1. Básicamente, se está inicializando x
variable con el valor de -1. Casting -1 a int resultará en -1 (operandos signed
obtendrán signo extendido en upcasts mientras que operandos unsigned
obtendrán extendida cero).
Se puede forzar el char
ser unsigned
añadiendo el prefijo unsigned
:
unsigned char x = 255;
El otro responde muy bien a explicar cómo su ejemplo "funciona", por lo que no van a explicar que de nuevo.
Sin embargo, permítanme observar que si lo que desea utilizar es un "entero sin signo de 8 bits", el uso justo <stdint.h>
de uint8_t
ya (y sus 16, 32, compañeros de 64 bits) y mantenerse alejado de todos los char
s, short
s y int
s en este mundo.