Imprimir caracteres hexadecimales en C

Resuelto Rayne asked hace 12 años • 8 respuestas

Estoy intentando leer una línea de caracteres y luego imprimir el equivalente hexadecimal de los caracteres.

Por ejemplo, si tengo una cadena donde "0xc0 0xc0 abc123"los primeros 2 caracteres están c0en hexadecimal y los caracteres restantes están abc123en ASCII, entonces debería obtener

c0 c0 61 62 63 31 32 33

Sin embargo, printfusar %xme da

ffffffc0 ffffffc0 61 62 63 31 32 33

¿Cómo obtengo el resultado que quiero sin "ffffff"? ¿Y por qué solo c0 (y 80) tiene el ffffff, pero no los demás caracteres?

Rayne avatar Nov 09 '11 10:11 Rayne
Aceptado

Estás viendo el ffffffporque charestá firmado en tu sistema. En C, funciones vararg como printfpromoverán todos los números enteros más pequeños que intto int. Dado que chares un número entero (un entero con signo de 8 bits en su caso), sus caracteres se promocionan a inttravés de una extensión de signo.

Dado que c0y 80tienen un bit inicial (y son negativos como un entero de 8 bits), se les extiende el signo mientras que los demás en su muestra no.

char    int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061

Aquí tienes una solución:

char ch = 0xC0;
printf("%x", ch & 0xff);

Esto enmascarará los bits superiores y mantendrá solo los 8 bits inferiores que desee.

Mysticial avatar Nov 09 '2011 04:11 Mysticial

De hecho, existe una conversión de tipos a int. También puede forzar el tipo a char usando el especificador %hhx.

printf("%hhX", a);

En la mayoría de los casos, también querrás establecer la longitud mínima para llenar el segundo carácter con ceros:

printf("%02hhX", a);

ISO/IEC 9899:201x dice:

7 Los modificadores de longitud y sus significados son: hh Especifica que el siguiente especificador de conversión d, i, o, u, x o X se aplica a un argumento char con signo o char sin firmar (el argumento se habrá promovido de acuerdo con las promociones de enteros, pero su valor se convertirá a char firmado o char sin firmar antes de imprimir); o que un seguidor

brutal_lobster avatar Nov 09 '2011 04:11 brutal_lobster

Puedes crear un carácter sin firmar:

unsigned char c = 0xc5;

Imprimirlo dará C5y no ffffffc5.

Sólo los caracteres mayores a 127 se imprimen con ffffffporque son negativos (el carácter está firmado).

O puede transmitir charmientras imprime:

char c = 0xc5; 
printf("%x", (unsigned char)c);
Hicham avatar Nov 09 '2011 05:11 Hicham

Puede utilizar hhpara saber printfque el argumento es un carácter sin firmar. Úselo 0para obtener relleno cero y 2establecer el ancho en 2. xo Xpara caracteres hexadecimales en minúsculas/mayúsculas.

uint8_t a = 0x0a;
printf("%02hhX", a); // Prints "0A"
printf("0x%02hhx", a); // Prints "0x0a"

Editar : Si a los lectores les preocupa la afirmación de 2501 de que de alguna manera estos no son los especificadores de formato "correctos", les sugiero que lean el printfenlace nuevamente. Específicamente:

Aunque %c espera un argumento int, es seguro pasar un char debido a la promoción de enteros que tiene lugar cuando se llama a una función variable.

Las especificaciones de conversión correctas para los tipos de caracteres de ancho fijo (int8_t, etc.) se definen en el encabezado <cinttypes>(C++) o <inttypes.h>(C) (aunque PRIdMAX, PRIuMAX, etc. es sinónimo de %jd, %ju, etc.) .

En cuanto a su punto sobre firmado versus sin firmar, en este caso no importa ya que los valores siempre deben ser positivos y caber fácilmente en un int con signo. De todos modos, no existe un especificador de formato hexideximal firmado.

Edición 2 : (edición "cuándo-admitir-que-estás-equivocado"):

Si lee el estándar C11 real en la página 311 (329 del PDF), encontrará:

hh: Especifica que el siguiente especificador de conversión d, i, o, u, xo Xse aplica a un argumento signed charo unsigned char(el argumento se habrá promovido de acuerdo con las promociones de enteros, pero su valor se convertirá a signed charo unsigned charantes de imprimir); o que el siguiente nespecificador de conversión se aplique a un puntero a un signed charargumento.

Timmmm avatar Oct 13 '2015 14:10 Timmmm