【问题标题】:Why printf show false value of an hex number [duplicate]为什么printf显示十六进制数字的错误值[重复]
【发布时间】:2018-01-28 06:54:17
【问题描述】:

代码

char a; 
a = 0xf1;
printf("%x\n", a);

输出

fffffff1

printf() 显示 4 个字节,恰好我们在 a 中有一个字节。

这种不当行为的原因是什么?

如何改正?

【问题讨论】:

  • 格式错误。试试int a
  • char a; --> unsigned char a;
  • 它被转换为一个整数,从而扩展了符号
  • A char 无论如何都会通过整数提升提升为 int....
  • @EsmaeelE 标准 C 中没有要求 ASCII 是使用的字符集。考虑到 C 也可以在使用 EBCDIC 的机器上运行。

标签: c hex printf


【解决方案1】:

您应该使用int a 而不是char a,因为char 是无符号的并且只能存储从0 到255 的1 个字节。 而十六进制数需要很多存储空间来存储它,并且int存储大小是2或4字节。所以这里最好使用int来存储十六进制数。

【讨论】:

  • 普通的char可能是signedunsigned;这取决于实现。
  • 在编译代码的时候提升?
  • 0xf1 只需要一个字节,所以unsigned char 就足够了。
  • 在 OP 的平台上 char 具体是 signed;这就是他们看到这种行为的原因。
  • @EsmaeelE--检查负数环绕:char x = -1; printf("%s\n", x < 0 ? "signed char" : "unsigned char");.
【解决方案2】:

printf 是可变参数函数,因此编译器会尽力而为,但无法检查格式说明符和参数类型之间的严格符合性。

在这里,您传递了带有 %x(整数,十六进制)格式说明符的 char

因此该值被提升为有符号整数(因为 > 127: 负字符和char 在大多数系统上都是有符号的,这是肯定的)

要么:

  • a 更改为int(最简单)
  • a 更改为 unsigned char(由 BLUEPIXY 建议),以处理促销中的登录
  • 将格式更改为%hhx,如各种文档中所述(请注意,在我的 gcc 6.2.1 编译器中,hhx 无法识别,即使 hx 可以识别)

请注意,编译器会在到达printf 之前警告您遇到问题:

gcc -Wall -Wpedantic test.c
test.c: In function 'main':
test.c:6:5: warning: overflow in implicit constant conversion [-Woverflow]
 a = 0xf1;

【讨论】:

  • 一些编译器无论如何都会做这个检查。 gcc 将产生警告,并在这种情况下将 char 转换为 int
  • @PeterJ 不在我的版本上(它是 6.2.1 的一个分支),但是谢谢,我使用了最大警告选项并收到警告之前。 gcc 可能会默默地将 char 转换为 int,但我没有看到任何警告(我收到错误数量的参数的警告)
  • @EsmaeelE 添加-Wextra-Woverflow...
  • 你有哪个 gcc 版本? gcc 自 2.95 以来有所改进。是时候升级了。价格便宜:)
  • 我的建议:保持-Wall -Wextra 的风格(有时-Wpedantic 有点过分)
【解决方案3】:

这种不当行为的原因是什么?

这个问题看起来像strangely similar 我回答过的另一个问题;它甚至使用相同的值 (0xf1)。在那个答案中,我提供了一些必要的信息来了解当您将一个小值(例如 char)传递给可变参数函数(例如 printf)时会发生什么转换。在这里重复这些信息是没有意义的。

这个问题确实不同,因为在那个问题中,原始值实际上不是0xf1;不可能是因为 char 类型是在该系统上签名的。如果您从<limits.h> 检查CHAR_MINCHAR_MAX,您还可能会发现您的char 类型是有符号的,因此0xf1 不适合作为char 内的整数值。

相反,它最终以实现定义的方式进行转换,这对我们大多数人来说意味着它可能最终以其中一个高位变为符号位。当这些值提升为int(为了传递给printf)时,会发生符号扩展以保留该值(即,值为-1 的char 应转换为具有int 的值为 -1,因此您的示例的基础表示可能会从 0xf1 转换为 0xfffffff1

printf("CHAR_MIN .. CHAR_MAX: %d .. %d\n", CHAR_MIN, CHAR_MAX);
printf("Does %d fit? %s\n", '\xFF', '\xFF' >= CHAR_MIN && '\xFF' <= CHAR_MAX ? "Yes!"
                                                                             : "No!");

printf("%d %X\n", (char) -1, (char) -1); // Both of these get converted to int
printf("%d %X\n", -1, -1);               // ... and so are equivalent to these

我该如何纠正?

使用可以适合值0xf1 的类型声明a,例如intunsigned char

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-12
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2016-08-22
    • 1970-01-01
    • 2017-01-13
    • 2017-03-09
    相关资源
    最近更新 更多