2011-12-09 18 views
8

Así que soy un poco novato en C y tengo curiosidad por descubrir por qué estoy teniendo este comportamiento inusual.¿Por qué C imprime mis valores hexadecimales incorrectamente?

Estoy leyendo un archivo de 16 bits a la vez y simplemente los imprimo de la siguiente manera.

#include <stdio.h> 

#define endian(hex) (((hex & 0x00ff) << 8) + ((hex & 0xff00) >> 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 como esto:

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

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

Respuesta

10

Esto se debe a la promoción de tipos enteros.

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

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

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


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

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

parece funcionar es porque su macro implícita es deshacerse de los 16 bits superiores.

2

Usted ha declarado implícitamente hex como un valor con signo (para que sea de escritura sin firmar unsigned short hex), de modo que cualquier valor por encima 0x8FFF se considera negativa. Cuando printf lo muestra como un valor int de 32 bits, se muestra extendido con unos, causando el Fs principal. 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.

Cuestiones relacionadas