【问题标题】:Subtracting Hexadecimals十六进制减法
【发布时间】:2016-03-29 15:17:25
【问题描述】:

当我将变量声明为浮点数并减去两个十六进制数时,每次编译和运行它时都会得到不同的答案。如果我声明一个整数变量,每次编译和运行代码时结果都保持不变。我不明白为什么每次我用相同的两个数字(0xFF0000 - 0xFF7FF)的差异进行编译时,将结果存储在浮点数中会发生变化

int main()
{
   float BlocksLeft = 0xFF0000 - 0xFF7FF;
   int BLeft = 0xFF0000 - 0xFF7FF;

   printf("%08x\n", BlocksLeft);
   printf("%08x\n", BLeft);
}

【问题讨论】:

  • 我正在使用这个在线编译器tutorialspoint.com/compile_c_online.php
  • 浮点数不是无符号整数,因此 '%x' 是 'BlocksLeft' 的非法格式说明符,导致 UB。
  • 要打印float 并查看其所有意义,请尝试printf("%.9e\n", BlocksLeft); %08x 用于无符号整数。
  • 您应该阅读 IEEE754 并更深入地了解doubles,然后再尝试将它们视为仅仅是十六进制值。因为由于四舍五入,您得到的实际上是预期的行为。如果你使用double 而不是float,也许你会得到更一致的行为。我提到双打是因为float 只是double 的一半大小。
  • @alk 网页应该启动 gcc -Wall 以及更多开箱即用的 -Wxx 选项。如果它不这样做,至少应该有一种方法让它记住你的选择。如果您不能这样做,请查找另一个在线编译器。如果有选项,很好(我在移动设备上看不到)。

标签: c hex subtraction


【解决方案1】:

以下行不正确:

printf("%08x\n", BlocksLeft);

%x 格式将指示编译器您提供的参数是一个 int。这会导致未定义的行为。我试图编译你的代码,我得到了:

>gcc -Wall -Wextra -Werror -std=gnu99 -o stackoverflow.exe stackoverflow.c
stackoverflow.c: In function 'main':
stackoverflow.c:15:4: error: format '%x' expects argument of type 'unsigned int', but argument 2 has type 'double' [-Werror=format=]
    printf("%08x\n", BlocksLeft);
    ^

请尝试以更强的警告级别编译,至少-Wall

您可以通过这种方式更正您的程序,例如:

#include <stdio.h>

int main()
{
    float BlocksLeft = 0xFF0000 - 0xFF7FF;
    int BLeft = 0xFF0000 - 0xFF7FF;

    printf("%08x\n", (int) BlocksLeft); // Works because BlocksLeft's value is non negative
    // or
    printf("%08x\n", (unsigned int) BlocksLeft);
    // or
    printf("%.8e\n", BlocksLeft);

    printf("%08x\n", BLeft);
}

【讨论】:

  • 详细信息:"%x" 用于unsigned"%x" 也适用于非负的int
  • 更多细节然后:"%x"unsigned: "...,x,X unsigned int 参数被转换..." C11 §7.21.6.1 8 fprintf功能。 "%x" 也适用于非负 int,因为“一种提升类型是有符号整数类型,另一种提升类型是相应的无符号整数类型,并且值在两种类型中都可以表示;” §6.5.2.2 6 函数调用...
猜你喜欢
  • 2012-05-27
  • 1970-01-01
  • 2015-04-11
  • 2014-12-22
  • 2017-12-21
  • 2018-07-26
  • 2011-12-09
  • 2012-04-08
  • 1970-01-01
相关资源
最近更新 更多