¿Por qué C imprime incorrectamente mis valores hexadecimales?

Así que soy un poco novato en C y tengo curiosidad por averiguar por qué estoy teniendo este comportamiento inusual.

Estoy leyendo un archivo de 16 bits a la vez y los estoy imprimiendo de la siguiente manera.

#include  #define endian(hex) (((hex & 0x00ff) <> 8)) int main(int argc, char *argv[]) { const int SIZE = 2; const int NMEMB = 1; FILE *ifp; //input file pointe FILE *ofp; // output file pointer int i; short hex; for (i = 2; i < argc; i++) { // Reads the header and stores the bits ifp = fopen(argv[i], "r"); if (!ifp) return 1; while (fread(&hex, SIZE, NMEMB, ifp)) { printf("\n%x", hex); printf("\n%x", endian(hex)); // this prints what I expect printf("\n%x", hex); hex = endian(hex); printf("\n%x", hex); } } } 

Los resultados se ven algo así:

 ffffdeca cade // expected ffffdeca ffffcade 0 0 // expected 0 0 600 6 // expected 600 6 

¿Puede alguien explicarme por qué la última línea de cada bloque no imprime el mismo valor que el segundo?

Esto se debe a la promoción de tipo entero.

Tus shorts están siendo promovidos implícitamente a int . (que es de 32 bits aquí) Así que estas son promociones de extensión de signo en este caso.

Por lo tanto, su printf() está imprimiendo los dígitos hexadecimales del int completo de 32 bits.

Cuando su valor short es negativo, la extensión de signo llenará los 16 bits superiores con unos, por lo que obtendrá ffffcade lugar de cade .


La razón por la cual esta línea:

 printf("\n%x", endian(hex)); 

Parece funcionar porque su macro se está deshaciendo implícitamente de los 16 bits superiores.

El marcador de posición %x en la cadena de formato interpreta el parámetro correspondiente como unsigned int .

Para imprimir el parámetro tan short , agregue un modificador de longitud h al marcador de posición:

 printf("%hx", hex); 

http://en.wikipedia.org/wiki/Printf_format_string#Format_placeholders

Usted ha declarado de forma implícita el hex como un valor con signo (para que sea sin signo escriba unsigned short hex sin unsigned short hex ), de modo que cualquier valor por encima de 0x8FFF se considere negativo. Cuando printf lo muestra como un valor int 32 bits, se extiende con el signo de unos, lo que genera las Fs . Cuando imprime el valor de retorno de endian antes de truncarlo asignándolo a hex los 32 bits completos están disponibles e impresos correctamente.