Tengo en lenguaje C números hexadecimales definidos en cadena:
char chars[] = "\xfb\x54\x9c\xb2\x10\xef\x89\x51\x2f\x0b\xea\xbb\x1d\xaf\xad\xf8";Entonces quiero comparar los valores con otro. No funciona y si imprimo el valor como:
printf("%02x\n", chars[0]); se escribe fffffffb . ¿Por qué es eso y cómo obtener el valor fb exactamente?
Esto se debe a la extensión del signo.
Cambio
printf("%02x\n", chars[0]);para
printf("%02x\n", (unsigned char)chars[0]); El especificador de formato %x leerá 4 bytes en una máquina de 32 bits. Como ha declarado chars como matriz de caracteres, al obtener el valor fb (valor negativo) se extenderá el signo como fffffffb , donde el MSB de fb se establece en todos los demás bits anteriores.
Consulte esto para obtener más detalles extensión de signo
Si hubiera declarado char chars[] como unsigned char chars[] entonces la impresión habría sido como se esperaba.
Según la mención estándar con respecto al especificador de formato %x con fprintf()
o,u,x,XEl argumento int sin signo se convierte a notación octal sin signo ( o ), decimal sin signo ( u ) o hexadecimal sin signo (x o X) en el estilo dddd ; [...]
Entonces, el tipo de argumento esperado para %x es unsigned int .
Ahora, printf() es una función variable, solo se aplica la regla de promoción predeterminada a sus argumentos. En su código, los chars son una matriz de tipo char (cuya firma depende de la implementación), en caso de
printf("%02x\n", chars[0]); el valor de chars[0] se promociona a un int que no es el tipo esperado para %x . Por lo tanto, la salida es incorrecta, ya que int y unsigned int no son del mismo tipo. [Consulte §6.7.2, C11 ]. Entonces, sin un elenco explícito como
printf("%02x\n", (unsigned int)chars[0]);invoca un comportamiento indefinido .
FWIW, si tiene un compilador compatible con C99, puede utilizar el modificador de longitud hh para solucionar esto, como
printf("%02hhx\n", (unsigned char)chars[0]);Es por la extensión del signo.
Esto funcionará como esperas:
printf("%02x\n", (unsigned char)chars[0]);