La multiplication de carbonisation et int ensemble en C
Question
Aujourd'hui, je trouve ce qui suit:
#include <stdio.h>
int main(){
char x = 255;
int z = ((int)x)*2;
printf("%d\n", z); //prints -2
return 0;
}
Donc, fondamentalement, je reçois un dépassement parce que la limite de taille est déterminée par les opérandes sur le côté droit du signe = ??
Pourquoi ne pas à int avant de multiplier le travail?
Dans ce cas, j'utilise char et int, mais si je l'utilise « long » et « long int » (C99), puis-je obtenir un comportement similaire. Est-il conseillé généralement contre faire des calculs avec des opérandes de différentes tailles?
La solution
char
peut être signé ou non signé, selon votre compilateur.
Dans votre cas, il semble être signé, et 255 est en dehors de la plage, il peut représenter (probablement, il ne peut représenter des nombres -128 à 127).
Le problème se produit lorsque vous attribuez 255 à votre variable char
-. Il en résulte une valeur définie de mise en œuvre, ce qui dans votre cas, semble être -1
Lorsque vous multipliez -1 par 2, vous obtenez -2. Pas de mystère là-bas. Le casting de (int)
ne fait rien -. Types plus étroits que int
sont toujours promus int
ou unsigned int
avant que les calculs sont faits avec eux
Autres conseils
Il semble que l'omble est signé sur votre plate-forme. Ainsi, le char x = 255
est effectivement le même que char x = -1
. Le casting à int n'a pas d'importance.
Essayez de changer cela à:
unsigned char x = 255;
Non, vous ne recevez pas un débordement sur la deuxième ligne (multiplication). Le problème est que votre compilateur utilise signed char
par défaut et 255 déversoirs et signifie -1. En gros, vous initialisez x
variable avec la valeur de -1. Coulée -1 int entraînera -1 (signed
opérandes s'extension de signe en upcasts tandis que opérandes unsigned
auront zéro étendu).
Vous pouvez forcer le char
être unsigned
en ajoutant le préfixe unsigned
:
unsigned char x = 255;
Les autres réponses expliquent bien comment votre exemple « oeuvres », je ne vais pas expliquer à nouveau.
Cependant, permettez-moi de souligner que si ce que vous voulez utiliser est un « entier non signé 8 bits », utilisez <stdint.h>
de uint8_t
déjà (et ses 16, 32, compagnons de 64bit) et tenir à l'écart de tous les char
s, short
s et int
s dans ce monde.