Comportement défini, en passant caractère printf(“%02X”
Je suis récemment tombé sur cette question, où l'OP était d'avoir des problèmes d'impression de la valeur hexadécimale d'une variable. Je crois que le problème peut être résumé par le code suivant:
#include <stdio.h>
int main() {
char signedChar = 0xf0;
printf("Signed\n”);
printf(“Raw: %02X\n”, signedChar);
printf(“Masked: %02X\n”, signedChar &0xff);
printf(“Cast: %02X\n", (unsigned char)signedChar);
return 0;
}
Cela donne le résultat suivant:
Signed
Raw: FFFFFFF0
Masked: F0
Cast: F0
Le format de chaîne de caractères utilisée pour chacun des tirages est %02X
, que j'ai toujours interprétée comme "l'impression fournis int
comme une valeur hexadécimale avec au moins deux chiffres".
Le premier cas, passe le signedCharacter en tant que paramètre et affiche la valeur faux (parce que les trois autres octets de la int
ont tous leurs bits).
Le second cas permet de contourner ce problème, par l'application d'un masque de bits (0xFF
) contre la valeur de supprimer tous mais l'octet le moins significatif, où la char
est stocké. Si cela fonctionne? Sûrement: signedChar == signedChar & 0xFF
?
Le troisième cas contourne le problème en jetant le caractère d'une unsigned char
(ce qui semble clair, les trois premiers octets?).
Pour chacun des trois cas ci-dessus, quelqu'un peut-il me dire si le comportement défini? Comment/Où?
int
obtenir une promotion à int
lorsqu'il est passé à printf.Depuis le sous-jacente représentation binaire des nombres n'est pas définie dans la norme C, la sortie exacte n'est pas spécifié.
R: Donc, dans le deuxième cas, la promotion de toujours avoir lieu avant que le masque est appliqué? Ou peut-il se produire après dans lequel le masque aurait aucun effet?
La ce paramètre de
char
la mise en œuvre est définie, par la manière. Si vous voulez signé un caractère, utilisez signed char
.vraiment? J'ai toujours supposé que les variables ont été signés par défaut à moins d'indication contraire. Est-il le même pour les entiers?
OriginalL'auteur forsvarir | 2011-05-20
Vous devez vous connecter pour publier un commentaire.
Je ne pense pas que ce comportement est complètement défini par c standard. Après tout, il dépend de la représentation binaire des valeurs signées. Je vais juste décrire comment il est susceptible de travailler.
(char)0xf0
qui peut être écrit comme(char)-16
est converti à(int)-16
sa représentation hexadécimale est0xfffffff0
.0xff
est de typeint
donc, avant de calculer&
,signedChar
est converti à(int)-16
.((int)-16) & ((int)0xff)
==(int)0x000000f0
.(unsigned char)0xf0
qui peut être écrit comme(unsigned char)240
est converti à(unsigned int)240
que hex c'est0x000000f0
(unsigned char)240
est converti en(int)240
comme par 6.3.1.1:2 dans le standard C99: “Si un int peut représenter toutes les valeurs du type d'origine, la valeur est convertie en int”Et ce qui est mieux/plus vite si je ne veux imprimer 2 symboles? Masqué ou en fonte?
OriginalL'auteur Piotr Praszmo