C – La impresión de valores int negativos como hexadecimal produce demasiados caracteres

Compile utilizando gcc 4.1.2 en CentOS-5 64 bit.

Imprimiendo un entero como una cadena hexadecimal de dos caracteres:

#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; } 

Como el valor es de solo 1 byte, espero que un valor entero de ‘-1’ imprima “0xFF”. Sin embargo, me sale:

  int negative var is  int positive var is  

Intenté abstraer esto en un búfer char * para imprimir 1 byte a la vez. Esto produjo los mismos resultados:

 #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 string, 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); } } 

Huellas dactilares:

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

Me puse a pensar que “char” se implementa en C como un tipo entero, así que decidí intentar cambiar “char * pByteBuff” por ” unsigned char * pByteBuff” en la función “print_hex”. Esto funcionó, y solo imprimió los dos caracteres que esperaba:

 int negative var is  Converted to FF! 

Si bien este problema se solucionó, la pregunta sigue siendo: ¿por qué una impresión explícita como valor hexadecimal de dos caracteres imprime 8 caracteres en lugar de los dos que se especifican?

Un int8_t irá a través de las promociones enteras habituales como un parámetro a una función variable como printf() . Esto normalmente significa que int8_t se convierte en int .

Sin embargo, "%X" está destinado a argumentos unsigned . Entonces conviértase primero en algún tipo sin signo y use un especificador de formato coincidente:

Para uint8_t , use PRIX8 . Con los tipos de ancho exactos, incluya para los especificadores correspondientes.

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

Con int8_t iNegVar = -1; , convertir a algún tipo sin signo antes de imprimir en hexadecimal

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

Es porque %x tiene el tamaño predeterminado de int.
Si quieres char, usa %hhx
O mejor, tienes las macros en , como PRIx8

Cuando pasa el valor char a sprintf () o cualquier otra función variadic C, se promueve a valor int -1 en este caso. Ahora lo imprime como unsigned int por la especificación “% X”, por lo que obtiene un número largo con FF. unsigned char en el otro lado se promociona a unsigned int por lo que obtiene un valor entero de 0xFF que se imprime como 2 símbolos.

Nota: el hecho de que especifique% X – unsigned int en el formato de printf() solo afecta la forma en que la función printf trata el valor que se le pasa. La promoción Char -> int ocurre antes de que printf() llame y el especificador de formato no tenga efecto, solo el tipo del valor que está pasando.