2009-11-20 14 views
7

Aquí hay un problema extraño que me ha estado sacudiendo por un tiempo.Imprimir los valores hexadecimales de una matriz char * en C da valores impares para la entrada binaria

El programa está escrito en C89, y lee un archivo en una matriz char * de 16 bytes a la vez (usando fread y un tamaño de sizeof (char)). El archivo está fopen'd con las banderas "rb". La matriz se pasa luego a una función que básicamente toma los 16 valores hexadecimales y los pega en una cadena, cada valor separado por un espacio.

Aquí es donde entra la rareza. La función produce un bonito volcado hexadecimal, 16 bytes a la vez, para una entrada de archivo de texto que tengo. Pero se arruina si lo pruebo en una pequeña imagen de mapa de bits - termino con salida en la cadena como ffffff88 en lugar de solo 88.

Los valores hexadecimales se colocan en la cadena de salida usando sprintf ("% 02x" , entrada [i]); en un bucle

¿Por qué funcionaría esto correctamente para algunos archivos pero no para otros?

Respuesta

9

Lo que se ve es el resultado de la extensión de signo de la char a int, utilizando unsigned char * o fundición a unsigned char antes de la fundición a int es (implícitamente?) Realiza debe arreglar el problema.

11

En C, la charla se trata como un valor con signo, a menos que lo especifique como sin signo. Parece que cuando pasas parámetros a una función, cuando el parámetro pasa a ser un carácter "relleno" se convierte en el tamaño de un número entero regular. Si no indicas el compilador en el sentido de que esto debe hacerse sin firmar, 128 se convierte en 0xFFFFFF80, y así sucesivamente.

Por lo tanto, la extensión del signo ocurre antes de que el formateador de impresión llegue a ver el valor. Lo que esto significa es que

printf("%02X", (unsigned) input[i]); 

no va a resolver su problema, ya que el valor de la entrada [i] será signo extendido, por lo que todos los valores de 128 a 255 son tratados como -127 a -1 y se convierten en 0xFFFFFF80 a 0xFFFFFF, a continuación, fundido, mientras que

printf("%02X", ((unsigned char *) input)[i]); 

hará el truco, pero es una especie de torpe y difícil de leer. Lo mejor es hacer que el tipo de entrada [] sea char sin signo en primer lugar.

Cuestiones relacionadas