Reputation: 23073
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
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
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
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