Ceasar
Ceasar

Reputation: 23073

Why does C print my hex values incorrectly?

So I'm a bit of a newbie to C and I am curious to figure out why I am getting this unusual behavior.

I am reading a file 16 bits at a time and just printing them out as follows.

#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);
     }   
   }
 }

The results look something like this:

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

Can anyone explain to me why the last line in each block doesn't print the same value as the second?

Upvotes: 11

Views: 22434

Answers (3)

timothyqiu
timothyqiu

Reputation: 1122

The placeholder %x in the format string interprets the corresponding parameter as unsigned int.

To print the parameter as short, add a length modifier h to the placeholder:

printf("%hx", hex);

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

Upvotes: 23

Borodin
Borodin

Reputation: 126722

You have implicitly declared hex as a signed value (to make it unsigned write unsigned short hex) so that any value over 0x8FFF is considered to be negative. When printf displays it as a 32-bit int value it is sign-extended with ones, causing the leading Fs. When you print the return value of endian before truncating it by assigning it to hex the full 32 bits are available and printed correctly.

Upvotes: 2

Mysticial
Mysticial

Reputation: 471209

This is due to integer type-promotion.

Your shorts are being implicitly promoted to int. (which is 32-bits here) So these are sign-extension promotions in this case.

Therefore, your printf() is printing out the hexadecimal digits of the full 32-bit int.

When your short value is negative, the sign-extension will fill the top 16 bits with ones, thus you get ffffcade rather than cade.


The reason why this line:

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

seems to work is because your macro is implicitly getting rid of the upper 16-bits.

Upvotes: 11

Related Questions