warning: comparing floating point with == or != is unsafe [-Wfloat-equal]

Ah, compiler warnings. We hate you, yet we need you.

Recently at my day job, I noticed we were running with a very low C compiler warning level. I decided to crank it up a bit then rebuild.

It was a disasters. Thousands of compiler warnings scrolled by as it churned away for about five minutes. Many were coming from header files provided by the tool company! Things like windows.h and even things they included from standard ANSI C headers like stdint.h. What a mess!

I was able to figure out how to disable certain warnings to clean up the ones I could not fix, leaving me with a ton of legitimate warnings in our own code.

Some were harmless (if you knew what you were doing), like comparing signed to unsigned values, which I’ve previously discussed. Some complained about missing or incorrect prototypes.

A favorite useful one is when it complains about initialized variables that could be accessed, such as:

int variable;

switch (something)
{
   case 1:
      variable = 10;
      break;

   default:
      break;
}

printd ("variable: %d\n", variable);

Above, if “something” did not match one of the case statements (1 in this example), it would never be set, and the print would be using whatever random crap was in the space occupied by “variable” later. This is a nice warning to have.

Others were about unused variables or unused parameters. For example:

int function (int notUsed)
{
     return 42;
}

Compiler warnings can notify you that you have a variable declared that isn’t getting used. You can tell the compiler “Yeah, I know” by doing this:

int function (int notUsed)
{
    (void)notUsed; // Not used!
    return 42;
}

Each time you clean up a warning like that, you tell the compiler (and others who inspect the code) “I meant to do that!” And, sometimes you find actual bugs that were hidden before.

I’ve written a bit about floating point issues in the past, but the warning today is this one:

warning: comparing floating point with == or != is unsafe [-Wfloat-equal]

Basically, while you can do…

int a;
int b;

if (a == b) { ...something... };

…you cannot…

float a;
float b;

if (a == b) { ...something...}

…at least, you can’t without getting a warning. Due to how floating point works, simple code may fail in interesting ways:

int main()
{
    float var1;

    var1 = 902.1;

    if (var1 == 902.1)
    {
        printf ("it is!\n");
    }
    else
    {
        printf ("it is NOT.\n");
    }

    return EXIT_SUCCESS;
}

What do you think that will print?

To be continued…

7 thoughts on “warning: comparing floating point with == or != is unsafe [-Wfloat-equal]

  1. lostwizard99

    I would expect that to print “It is!” for the simple reason that the floating point conversion of 902.1 should be the same in both cases, including any rounding and imprecision. Also, a sufficiently smart compiler will optimize that into simply printing “It is!” but I’m assuming optimizations are off.

    On the other hand, if you had something like 902.025 + 0.075 being calculated at runtime, it gets more complicated and depends on things like the underlying floating point representation, the floating point implementation, etc.

    Reply
      1. lostwizard99

        Ahh, right. I didn’t take into account “the usual type promotions”. Yeah, it won’t match in that case since the conversion would have been truncated when storing in the variable but the constant wouldn’t be. Thus, they wouldn’t match since 0.1 yields a repeating sequence after the binary point.

        Reply
        1. Allen Huffman Post author

          Unlike me, you actually understand what is going on with these things. :) I just updated my work code using fabs() and will share that next, and hopefully no one will tell me how horribly I did it.

          Reply
  2. MiaM

    Side track: Were there ever a float format with 10 exponent instead of 2 exponent? It would take far more computing power to use, but it would get rid of this kind of problem.

    Reply
  3. Pingback: warning: comparing floating point with == or != is unsafe [-Wfloat-equal] – Part 2 | Sub-Etha Software

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.