Estoy tratando de leer en una línea de caracteres, luego imprimir el equivalente hexadecimal de los caracteres.
Por ejemplo, si tengo una cadena "0xc0 0xc0 abc123"
, es decir , donde los primeros 2 caracteres están c0
en hexadecimal y los caracteres restantes están abc123
en ASCII, entonces debería obtener
c0 c0 61 62 63 31 32 33
Sin embargo, printf
usar %x
me da
ffffffc0 ffffffc0 61 62 63 31 32 33
¿Cómo obtengo el resultado que quiero sin el "ffffff"
? ¿Y por qué solo c0 (y 80) tiene el ffffff
, pero no los otros caracteres?
"\xc0\xc0abc123"
Respuestas:
Estás viendo el
ffffff
porquechar
está firmado en tu sistema. En C, vararg funciona comoprintf
promoverá todos los enteros menores queint
aint
. Dado quechar
es un entero (entero de 8 bits con signo en su caso), sus caracteres se promocionan aint
través de la extensión de signo.Dado que
c0
y80
tienen un bit inicial de 1 bit (y son negativos como un entero de 8 bits), se están extendiendo con el signo, mientras que los demás en su muestra no.He aquí una solución:
Esto enmascarará los bits superiores y mantendrá solo los 8 bits inferiores que desee.
fuente
unsigned char
conversión a es una instrucción más pequeña en gcc4.6 para x86-64 ...x
requiere un tipo sin firmar, pero ch se promueve a int. El código correcto sería simplemente fundido ch a firmar, o usar un yeso para unsigned char y el especificador:hhx
.printf("%x", 0)
, no se imprime nada.printf("%.2x", 0);
que aumentará los caracteres mínimos dibujados a 2. Para establecer un máximo, anteponga el. con un número. Por ejemplo, puede forzar solo 2 caracteres dibujados haciendoprintf("%2.2x", 0);
printf("%x", ch & 0xff)
debería ser mejor que simplemente usarprintf("%02hhX", a)
como en la respuesta de @ brutal_lobster ?De hecho, existe una conversión de tipo a int. También puede forzar el tipo a char utilizando el especificador% hhx.
En la mayoría de los casos, también querrá establecer la longitud mínima para llenar el segundo carácter con ceros:
ISO / IEC 9899: 201x dice:
fuente
Puede crear un carácter sin firmar:
Imprimiéndolo dará
C5
y noffffffc5
.Solo los caracteres mayores de 127 se imprimen con el
ffffff
porque son negativos (el carácter está firmado).O puede emitir
char
mientras imprime:fuente
Probablemente esté almacenando el valor 0xc0 en una
char
variable, lo que probablemente sea un tipo con signo, y su valor sea negativo (conjunto de bits más significativo). Luego, al imprimir, se convierteint
y para mantener la equivalencia semántica, el compilador rellena los bytes adicionales con 0xff, por lo que el negativoint
tendrá el mismo valor numérico que el negativochar
. Para solucionar este problema, simplemente envíe aunsigned char
al imprimir:fuente
Puede usar
hh
para saberprintf
que el argumento es un carácter sin firmar. Úselo0
para obtener relleno de cero y2
para establecer el ancho en 2.x
oX
para caracteres hexadecimales en minúsculas / mayúsculas.Editar : Si los lectores están preocupados por la afirmación de 2501 de que de alguna manera no son los especificadores de formato "correctos", sugiero que lean el
printf
enlace nuevamente. Específicamente: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 con signo. De todos modos, no hay un especificador de formato hexadecimal firmado.
Edición 2 : ( edición "cuándo-admitir-que-está-equivocado"):
Si lee el estándar C11 actual en la página 311 (329 del PDF), encontrará:
fuente
inttypes.h
char
yunsigned char
se promueve aint
) [ en.cppreference.com/w/cpp/language/variadic_arguments] . Solo necesitaría usar los especificadores PRI para cosas que no encajan en su plataformaint
, por ejemplounsigned int
.%x
es correcto para unsigned int no int. Los tipos char y unsigned char se promueven a int. Además, no hay garantía de que uint8_t esté definido como carácter sin firmar.Probablemente esté imprimiendo desde una matriz de caracteres firmada. Imprima desde una matriz de caracteres sin firmar o enmascare el valor con 0xff: por ejemplo, ar [i] y 0xFF. Los valores de c0 se extienden en signo porque el bit alto (signo) está establecido.
fuente
Intente algo como esto:
Que produce esto:
fuente