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.