0

When I declare a variable as float and subtract two hexadecimal numbers, I keep getting different answer everytime I compile and and run it. Where as the if I declare an integer variable the result stays the same everytime I compile and run the code. I don't understand why storing the result in float changes everytime I compile with the difference of the same two numbers (0xFF0000 - 0xFF7FF)

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

   printf("%08x\n", BlocksLeft);
   printf("%08x\n", BLeft);
}
Syed Rumman
  • 99
  • 1
  • 1
  • 7
  • I am using this online compiler http://www.tutorialspoint.com/compile_c_online.php – Syed Rumman Mar 29 '16 at 15:19
  • 4
    A float is not an unsigned integer, and so '%x' is an illegal format specifier for 'BlocksLeft', leading to UB. – Martin James Mar 29 '16 at 15:21
  • To print a `float` and see all its significance, try `printf("%.9e\n", BlocksLeft);` `%08x` is for unsigned integers. – chux - Reinstate Monica Mar 29 '16 at 15:23
  • You should read up on IEEE754 and understand `double`s a bit deeper before attempting to look at them as mere hexadecimal values. Because what you're getting is actually intended behaviour due to rounding. If you were to use `double` instead of float, perhaps you'd get more consistent behavour. I'm mentioning doubles because `float` is just half the size of a `double`. – Shark Mar 29 '16 at 15:23
  • Do not use this online compiler. It is nit set up correctly. I have searched for 10 minites and couldn't find how to enable warnings. You should never compile anything without enabling warnings. – n. m. could be an AI Mar 29 '16 at 15:30
  • @n.m. Just *type in* `gcc -Wall -Wextra -pedantic -Wconversion main.c -o main`. – alk Mar 29 '16 at 15:53
  • @alk I know how to get by without an IDE thank you very much. I was looking for a way to set up the IDE correctly. – n. m. could be an AI Mar 29 '16 at 16:00
  • @n.m. Sry, I was just referring to the *web-page's functionality in its whole*. I never wanted to express any doubts in your expertise on how to use GCC! – alk Mar 29 '16 at 16:06
  • And BTW, I just figured out, that under "Project->Compile Options" one can modify the "compile "command. – alk Mar 29 '16 at 16:10
  • 1
    @alk The web page should launch gcc -Wall plus maybe more -Wxx options out of the box. If it doesn't do that, there should be at least a way to make it remember your choice. If you can't do that, find another online compiler. If there are options, good (I can't see them on mobile). – n. m. could be an AI Mar 29 '16 at 16:21
  • @chux I did not know that, I will add it to my answer. – jdarthenay Mar 29 '16 at 16:28
  • @jdarthenay See [this](http://stackoverflow.com/q/16839658/2410359) for details. I should have recommended `"%.8e\n"`, but that is a minor point. – chux - Reinstate Monica Mar 29 '16 at 16:36

1 Answers1

4

The following line is incorrect:

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

%x format will indicate compiler the argument you give is an int. This lead to undefined behavior. I tried to compile your code and I got:

>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);
    ^

Please, try to compile with stronger warning level, at least -Wall.

You can correct your program this way, for instance:

#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);
}
jdarthenay
  • 3,062
  • 1
  • 15
  • 20
  • Detail: `"%x"` is for `unsigned`. `"%x"` also works with non-negative `int`. – chux - Reinstate Monica Mar 29 '16 at 16:40
  • More details then: `"%x"` is for `unsigned`: "...,x,X The `unsigned int` argument is converted ... " C11 §7.21.6.1 8 The `fprintf` function. `"%x"` also works with non-negative `int` because "one promoted type is a signed integer type, the other promoted type is the corresponding unsigned integer type, and the value is representable in both types;" §6.5.2.2 6 Function calls `...` – chux - Reinstate Monica Mar 29 '16 at 17:01