为什么C打印我的十六进制值不正确?

时间:2011-12-09 04:56:23

标签: c

所以我对C来说是一个新手,我很想知道为什么我会遇到这种不寻常的行为。

我一次读取16位文件,然后按如下方式打印出来。

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

结果看起来像这样:

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

任何人都可以向我解释为什么每个块中的 last 行不会与第二行打印相同的值吗?

3 个答案:

答案 0 :(得分:18)

格式字符串中的占位符%x将相应的参数解释为unsigned int

要将参数打印为short,请在占位符中添加长度修饰符h

printf("%hx", hex);

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

答案 1 :(得分:10)

这是由于整数类型提升。

您的shorts被隐式提升为int。 (这里是32位)所以这些是签名扩展促销。

因此,您的printf()正在打印出完整32位int的十六进制数字。

当您的short值为负数时,符号扩展名会将前16位填充为1,因此您获得ffffcade而不是cade


这一行之所以:

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

似乎工作是因为你的宏隐含地摆脱了高16位。

答案 2 :(得分:2)

您已将hex隐式声明为有符号值(使其成为无符号写unsigned short hex),以便0x8FFF以上的任何值都被视为否定。当printf将其显示为32位int值时,会使用1进行符号扩展,从而导致前导Fs。在通过将endian分配给hex之前打印返回值{{1}}时,可以使用完整的32位并正确打印。