J'essaie de lire une ligne de caractères, puis d'imprimer l'équivalent hexadécimal des caractères.
Par exemple, si j'ai une chaîne qui est "0xc0 0xc0 abc123"
, où les 2 premiers caractères sont c0
en hexadécimal et les caractères restants sont abc123
en ASCII, alors je devrais obtenir
c0 c0 61 62 63 31 32 33
Cependant, l' printf
utilisation %x
me donne
ffffffc0 ffffffc0 61 62 63 31 32 33
Comment obtenir la sortie souhaitée sans le "ffffff"
? Et pourquoi est-ce que seul c0 (et 80) a le ffffff
, mais pas les autres caractères?
"\xc0\xc0abc123"
Réponses:
Vous voyez le
ffffff
carchar
est signé sur votre système. En C, les fonctions vararg telles queprintf
favoriseront tous les entiers plus petits queint
àint
. Puisqu'ilchar
s'agit d'un entier (entier signé 8 bits dans votre cas), vos caractères sont promusint
via l'extension de signe.Puisque
c0
et80
ont un premier bit de 1 bit (et sont négatifs en tant qu'entier 8 bits), ils sont étendus de signe alors que les autres de votre échantillon ne le font pas.Voici une solution:
Cela masquera les bits supérieurs et ne conservera que les 8 bits inférieurs souhaités.
la source
unsigned char
est une instruction plus petite dans gcc4.6 pour x86-64 ...x
nécessite un type non signé, mais ch est promu en int. Le code correct serait tout simplement jeté à ch non signé, ou utiliser un casting pour unsigned char et le prescripteur:hhx
.printf("%x", 0)
, rien n'est imprimé.printf("%.2x", 0);
ce qui augmentera le nombre minimum de caractères dessinés à 2. Pour définir un maximum, ajoutez le. avec un nombre. Par exemple, vous ne pouvez forcer que 2 caractères dessinés en faisantprintf("%2.2x", 0);
printf("%x", ch & 0xff)
devrait être mieux que d'utiliser simplementprintf("%02hhX", a)
comme dans la réponse de @ brutal_lobster ?En effet, il existe une conversion de type en int. Vous pouvez également forcer le type à char en utilisant le spécificateur% hhx.
Dans la plupart des cas, vous voudrez également définir la longueur minimale pour remplir le deuxième caractère avec des zéros:
ISO / CEI 9899: 201x dit:
la source
Vous pouvez créer un caractère non signé:
L'imprimer donnera
C5
et nonffffffc5
.Seuls les caractères supérieurs à 127 sont imprimés avec le
ffffff
car ils sont négatifs (le caractère est signé).Ou vous pouvez lancer le
char
tout en imprimant:la source
Vous stockez probablement la valeur 0xc0 dans une
char
variable, ce qui est probablement un type signé, et votre valeur est négative (ensemble de bits le plus significatif). Ensuite, lors de l'impression, il est converti enint
, et pour conserver l'équivalence sémantique, le compilateur remplit les octets supplémentaires avec 0xff, de sorte que le négatifint
aura la même valeur numérique que votre négatifchar
. Pour résoudre ce problème, il vous suffit de lancerunsigned char
lors de l'impression:la source
Vous pouvez utiliser
hh
pour indiquerprintf
que l'argument est un caractère non signé. Utilisez0
pour obtenir un remplissage nul et2
pour définir la largeur sur 2.x
ouX
pour les caractères hexadécimaux minuscules / majuscules.Edit : Si les lecteurs sont préoccupés par l'affirmation de 2501 selon laquelle ce n'est pas les spécificateurs de format `` corrects '', je suggère qu'ils relisent le
printf
lien . Plus précisément:Quant à son point sur signé vs non signé, dans ce cas, cela n'a pas d'importance car les valeurs doivent toujours être positives et s'intégrer facilement dans un int signé. Il n'y a de toute façon aucun spécificateur de format hexideximal signé.
Edit 2 : ( édition "quand admettre que vous vous trompez"):
Si vous lisez la norme C11 actuelle à la page 311 (329 du PDF), vous trouvez:
la source
inttypes.h
char
etunsigned char
sont promus enint
) [ en.cppreference.com/w/cpp/language/variadic_arguments] . Vous n'auriez besoin d'utiliser les spécificateurs PRI que pour les choses qui ne correspondent pas à votre plateint
- forme , par exempleunsigned int
.%x
est correct pour unsigned int pas int. Les types char et unsigned char sont promus en int. De plus, il n'y a aucune garantie que uint8_t soit défini comme un caractère non signé.Vous imprimez probablement à partir d'un tableau de caractères signé. Soit imprimer à partir d'un tableau de caractères non signé, soit masquer la valeur avec 0xff: par exemple ar [i] & 0xFF. Les valeurs c0 sont en cours d'extension de signe car le bit haut (signe) est activé.
la source
Essayez quelque chose comme ceci:
Ce qui produit ceci:
la source