pantalla - imprimir hexadecimal en c
Imprimir caracteres hexadecimales en C (7)
De hecho, hay conversión de tipo a int. También puede forzar el tipo a char usando el especificador% hhx.
printf("%hhX", a);
Intento leer en una línea de caracteres y luego imprimir el equivalente hexadecimal de los caracteres.
Por ejemplo, si tengo una cadena que es "0xc0 0xc0 abc123"
, donde los primeros 2 caracteres son c0
en hexadecimal y los caracteres restantes son abc123
en ASCII, entonces debería obtener
c0 c0 61 62 63 31 32 33
Sin embargo, printf
usando %x
me da
ffffffc0 ffffffc0 61 62 63 31 32 33
¿Cómo obtengo el resultado que quiero sin el "ffffff"
? ¿Y por qué es que solo c0 (y 80) tiene el ffffff
, pero no los otros personajes?
Estás viendo el ffffff
porque char
está ffffff
en tu sistema. En C, las funciones vararg como printf
promoverán todos los enteros más pequeños que int
a int
. Como char
es un entero (entero con signo de 8 bits en su caso), sus caracteres se están promoviendo a int
través de la extensión de signo.
Como c0
y 80
tienen un valor de 1 bit (y son negativos como un número entero de 8 bits), se están extendiendo los signos, mientras que los otros en la muestra no lo hacen.
char int
c0 -> ffffffc0
80 -> ffffff80
61 -> 00000061
Aquí hay una solución:
char ch = 0xC0;
printf("%x", ch & 0xff);
Esto enmascara los bits superiores y conserva solo los 8 bits más bajos que desee.
Probablemente esté almacenando el valor 0xc0 en una variable char
, lo que probablemente sea un tipo firmado, y su valor sea negativo (el conjunto de bits más significativo). Luego, al imprimir, se convierte a int
, y para mantener la equivalencia semántica, el compilador rellena los bytes adicionales con 0xff, por lo que el int
negativo tendrá el mismo valor numérico de su char
negativo. Para solucionar esto, solo envía a unsigned char
al imprimir:
printf("%x", (unsigned char)variable);
Probablemente esté imprimiendo desde una matriz de caracteres firmada. Imprima desde una matriz de caracteres sin signo o enmascare el valor con 0xff: por ejemplo, ar [i] y 0xFF. Los valores de c0 se están extendiendo por signo porque se establece el bit alto (signo).
Pruebe algo como esto:
int main()
{
printf("%x %x %x %x %x %x %x %x/n",
0xC0, 0xC0, 0x61, 0x62, 0x63, 0x31, 0x32, 0x33);
}
Que produce esto:
$ ./foo
c0 c0 61 62 63 31 32 33
Puede crear un char sin signo:
unsigned char c = 0xc5;
Imprimirlo dará C5
y no ffffffc5
.
Solo los caracteres más grandes que 127 se imprimen con el ffffff
porque son negativos (el carácter está firmado).
O puede lanzar el char
mientras imprime:
char c = 0xc5;
printf("%x", (unsigned char)c);
Puede usar hh
para decirle a printf
que el argumento es un char sin signo. Use 0
para obtener relleno cero y 2
para establecer el ancho a 2. x
X
para caracteres hexadecimales de mayúscula / minúscula.
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, no se trata de los especificadores de formato "correctos", sugiero que vuelvan a leer el printf . Específicamente:
Aunque% c espera el argumento int, es seguro pasar un char debido a la promoción entera que tiene lugar cuando se llama a una función variadic.
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. son sinónimos de% jd,% ju, etc.) .
En cuanto a su punto sobre firmado vs no firmado, en este caso no importa ya que los valores siempre deben ser positivos y encajar fácilmente en un int firmado. No hay ningún especificador de formato hexideximal firmado de todos modos.
Edición 2 : ( edición de "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
,x
oX
aplica a un argumentounsigned char
ounsigned char
(el argumento se habrá promocionado de acuerdo con las promociones enteras, pero su valor se convertirá ensigned char
osigned char
unsigned char
antes de imprimir); o que un especificador de conversiónn
siguiente se aplica a un puntero a un argumentosigned char
.