This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Suggested new compiler warning: explicit cast from real to unsigned int.

Although an explicite cast looks like the programmer knew, the intended behaviour may need two casts.
I wanted to "infinitely" accumulate possibly small, possibly negative increments (float i) in a modulo counter consisting of an unsigned integer variable (uint32_t n) and a real variable (float f) for the fractional part.

f += i;
n += (uint32_t)f; // should read n += (uint32_t)(int32_t)f;
f -= (int32_t)f;

This worked with several compilers for PC platforms (gcc, lcc32, VS C++) and with the c6000 compiler for an OMAP L138, but the counter failed to decrease with the ARM5.1 compiler for the 7R4 core.

I now know that this is implementation defined behaviour as of C99 6.3.1.4, but none of the compilers emitted a warning nor does lint.

May be the warning can be limited to the unexcpected behaviour (where the expected behaviour is the modulo arithmetic guaranteed by C99 6.3.1.3 for the signed to unsigned cast).

Thank you

  • Rainald Koch said:
    the intended behaviour may need two casts.

    The words "intended behavior" are key here.  There is no way for the compiler to know the intention of the programmer.  And lacking that knowledge, there is nothing the compiler can do to help.

    Thanks and regards,

    -George

  • The C standard says that casting a negative float value to an unsigned integer is undefined behavior.  Consider the case that f contains an integer value equal to UINT32_MAX.  In that case, you would not want the expression ((uint32_t)f) to narrow the value down to int32_t first, because you won't preserve the correct value.  The C standard leaves it as the programmer's responsibility to make sure any cast of a float to an integer uses an integer type that can correctly represent the integer part of the float value. 

    If we were to introduce a warning every time a float value were cast to an unsigned integer value, there could potentially be a lot of expressions that were written correctly and work just fine to suddenly start getting a warning.

  • "Consider the case that f contains an integer value equal to UINT32_MAX." -- the mantissa of float is less than 32 bit. If I would need 32 bit precision (given that the signal provides it), f would be a double and my expression would be (uint32_t)(int64_t)f.  If not, I would scale down f by changing the unit.

    "casting a negative float value to an unsigned integer is undefined behavior" -- a good reason for a warning. The extra reason here is that we are used to get the modulo behaviour when using unsigned integers. It is guaranteed by the standard within the realm of integer types, and it also works with real types for many machines.

    "work just fine" -- currently. It may not work on another platform (other customer, obsolescence). It may stop working when the experts already have left the company.

    In my case, it stopped working when the customer changed to the Hercules(tm) "Safety" Microcontroller, which turned out to work differently.

    But it is probably better not to rely on any tool for code analysis.

  • The compiler may be aware that it, not the standard, defines the behaviour and emit a warning.