'UINT_MAX->float->uint32_t Results in 0 on VC++

As part of some work to port some code to windows I came across an issue where a cast of uint32_t max value -> float -> uint32_t resulted in 0 when building with the visual c++. I distilled the problem down to a simple program that shows the issue when run through different compilers.

#include <iostream>
#include <limits>

using namespace std;

int main()
{
    uint32_t r1 = numeric_limits<uint32_t>::max();
    float r2 = static_cast<float>(numeric_limits<uint32_t>::max());
    uint32_t r3 = static_cast<uint32_t>(static_cast<float>(numeric_limits<uint32_t>::max()));


    cout << "r1 = " << r1 << endl
    << "r2 = " << r2 << endl
    << "r3 = " << r3 << endl;

    return 0;
}

When this is run through http://webcompiler.cloudapp.net/ the output for r3 is 0 but when run through https://ideone.com/ylf74N r3 is the max value.

I'm guessing that there's a +1 happening in the conversion back to uint32_t when it's UINT_MAX but I'm wondering if anyone knows why or what precisely is happening?



Solution 1:[1]

On your system it appears that float is a 32 bit type, probably IEEE754 (but note that the standard does not insist on that).

numeric_limits<uint32_t>::max() is 4294967295.

This is too big for your float. (The largest odd number that can be accommodated in an IEEE754 32 bit floating point is 8388607).

So your number gets rounded up to 4294967296. (This is the closet number that can be accommodated).

Of course, on converting this back to uint32_t causes it to wrap around to 0.

As for the other system, we know the float is 32 bits due to the sizeof output. The compiler is making an optimisation in error.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1