'Casting from long double to unsigned long long appears broken in the MSVC C++ compiler

Consider the following code:

#include <iostream>

using namespace std;

int main(int argc, char *argv[])
{
    long double test = 0xFFFFFFFFFFFFFFFF;
    cout << "1: " << test << endl;
    unsigned long long test2 = test;
    cout << "2: " << test2 << endl;
    cout << "3: " << (unsigned long long)test << endl;
    return 0;
}

Compiling this code with GCC g++ (7.5.0) and running produces the following output as expected:

1: 1.84467e+19
2: 18446744073709551615
3: 18446744073709551615

However compiling this with the Microsoft Visual C++ compiler (16.8.31019.35, both 64-bit and 32-bit) and running produces the following output:

1: 1.84467e+19
2: 9223372036854775808
3: 9223372036854775808

When casting a value to an unsigned long long, the MSVC compiler won't give a value lager than the max of a (signed) long long.

Am I doing something wrong? 

Am I running into a compiler limitation that I do not know about?

Does anyone know of a possible workaround to this problem?



Solution 1:[1]

Because a MSVC long double is really just a double (as pointed out by @drescherjm in the comments), it does not have enough precision to contain the exact value of 0xFFFFFFFFFFFFFFFF. When this value is stored in the long double it gets "rounded" to a value that is lager than 0xFFFFFFFFFFFFFFFF. This then causes undefined behaviour when converting to an unsigned long long.

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 ManInBlack