web-dev-qa-db-fra.com

Pourquoi printf n'imprime-t-il pas un seul octet lors de l'impression hexadécimale?

pixel_data Est un vector de char.

Quand je fais printf(" 0x%1x ", pixel_data[0] ) je m'attends à voir 0xf5.

Mais j'obtiens 0xfffffff5 Comme si j'imprimais un entier de 4 octets au lieu d'un octet.

Pourquoi est-ce? J'ai donné à printf un char à imprimer - c'est seulement 1 octet, alors pourquoi printf imprime-t-il 4?

NB. l'implémentation de printf est enveloppée dans une API tierce mais vous vous demandez si c'est une fonctionnalité de printf standard?

34
BeeBand

Vous obtenez probablement une forme bénigne de comportement indéfini car le %x le modificateur attend un unsigned int un paramètre et un char seront généralement promus en int lorsqu'ils seront passés à une fonction varargs.

Vous devez explicitement convertir le caractère en un unsigned int pour obtenir des résultats prévisibles:

printf(" 0x%1x ", (unsigned)pixel_data[0] );

Notez qu'un largeur de champ de un n'est pas très utile. Il spécifie simplement le nombre minimum de chiffres à afficher et au moins un chiffre sera nécessaire dans tous les cas.

Si char sur votre plate-forme est signée, cette conversion convertira les valeurs négatives de char en grandes unsigned int valeurs (par exemple fffffff5). Si vous souhaitez traiter les valeurs d'octets comme des valeurs non signées et ne prolonger que zéro lors de la conversion en unsigned int Tu devrais utiliser unsigned char pour pixel_data, ou cast via unsigned char ou utilisez une opération de masquage après la promotion.

par exemple.

printf(" 0x%x ", (unsigned)(unsigned char)pixel_data[0] );

ou

printf(" 0x%x ", (unsigned)pixel_data[0] & 0xffU );
53
CB Bailey

Mieux utiliser les drapeaux de format standard

printf(" %#1x ", pixel_data[0] );

alors votre compilateur met le préfixe hexadécimal pour vous.

7
user411313

Utilisation %hhx

printf("%#04hhx ", foo);
4
domen

Le modificateur length est la longueur minimale.

3
leppie

Le spécificateur de largeur dans printf est en fait min-width. Vous pouvez faire printf(" 0x%2x ", pixel_data[0] & 0xff) pour imprimer les octets de poids faible (remarque 2, pour réellement imprimer deux caractères si pixel_data[0] est par exemple 0xffffff02).

2
phadej