C – Imprimer des valeurs int négatives au format hexadécimal génère trop de caractères

Comstackz avec gcc 4.1.2 sur CentOS-5 64 bits.

Imprimer un entier sous forme de chaîne hexagonale de deux caractères:

#include  #include  int main(void) { int8_t iNegVar = -1; int8_t iPosVar = 1; printf(" int negative var is \n", iNegVar); printf(" int positive var is \n", iPosVar); return 0; } 

Étant donné que la valeur n’est que de 1 octet, je suppose qu’une valeur entière de «-1» afficherait “0xFF”. Cependant, je reçois:

  int negative var is  int positive var is  

J’ai essayé de résumer ceci à un char * buffer pour imprimer 1 octet à la fois. Cela a donné les mêmes résultats:

 #include  #include  void print_hex(void* pBuffer, uint8_t uiBufSize); int main(void) { int8_t iNegVar = -1; int8_t iPosVar = 1; printf(" int negative var is \n", iNegVar); print_hex(&iNegVar, 1); //pass by reference printf(" int positive var is \n", iPosVar); print_hex(&iPosVar, 1); //pass by reference return 0; } void print_hex(void* pBuffer, uint8_t uiBufSize) { int i; char pTmp[3]; //Holds 2-character ssortingng, plus NULL char* pByteBuff = pBuffer; //Use char* to parse byte-by-byte for(i = 0; i < uiBufSize; i++) //Process all bytes in buffer { sprintf(pTmp, "%02X", pByteBuff[i]); //store each byte as 2-character string in "pTmp" printf(" Converted to %s!\n\n", pTmp); } } 

Impressions:

 int negative var is  Converted to FFFFFFFF! int positive var is  Converted to 01! 

Je pensais que “char” était implémenté dans C en tant que type entier, alors j’ai décidé d’essayer de remplacer “char * pByteBuff” par ” unsigned char * pByteBuff” dans la fonction “print_hex”. Cela a fonctionné et n’a imprimé que les deux personnages que j’attendais:

 int negative var is  Converted to FF! 

Bien que cela “corrige” mon problème, la question demeure: pourquoi une impression explicite sous forme de valeur hexadécimale à deux caractères imprime-t-elle 8 caractères au lieu des deux spécifiés?

Un int8_t passera par les promotions entières habituelles en tant que paramètre d’une fonction variadic telle que printf() . Cela signifie généralement que int8_t est converti en int .

Pourtant, "%X" est destiné aux arguments unsigned . Commencez donc par utiliser un type non signé et utilisez un spécificateur de format correspondant:

Pour uint8_t , utilisez PRIX8 . Avec les types de largeur exacte, incluez pour les spécificateurs correspondants.

 #include  printf(" int negative var is <%02" PRIX8 ">\n", iNegVar);` 

Avec int8_t iNegVar = -1; , convertir en un type non signé avant d’imprimer en hexadécimal

 printf(" int negative var is <%02" PRIX8 ">\n", (uint8_t) iNegVar);` 

C’est parce que %x a la taille par défaut de int.
Si vous voulez un caractère, utilisez %hhx
Ou mieux, vous avez les macros dans , comme PRIx8

Lorsque vous transmettez une valeur char à sprintf () ou à une autre fonction C variadique, elle est promue à la valeur int -1 dans ce cas. Maintenant, vous l’imprimez en tant que unsigned int selon la spécification “% X”, vous obtenez donc un nombre long avec FF. unsigned char sur un autre côté promu en unsigned int afin d’obtenir une valeur entière 0xFF imprimée sous la forme de 2 symboles.

Remarque: le fait de spécifier% X – unsigned int dans le formatage printf() affecte uniquement la manière dont la fonction printf traite la valeur qui lui est transmise. Char -> int survient avant l’appel de printf() et si le spécificateur de format n’a pas d’effet, seul le type de la valeur que vous transmettez.