ctype-conversiondoubleformat-specifierslong-long

Given a double value x, why (signed long long)(x) != *(signed long long *)(&x)?


I wonder why the code below prints "wrong".

double x = 0x8000000000000000;
signed long long v1 = (signed long long)(x);
signed long long v2 = *(signed long long *)(&x);
printf( v1 == v2? "correct\n" : "wrong\n" );

I tried to print out binary representation of v1 and v2 respectively by code below:

printf( "v1 = 0b" );
for ( int i = 63; i > 0; i-- ) {
    printf( "%d", ( ( v1 >> i ) & 1 ) );
}
printf( "\n" );

printf( "v2 = 0b" );
for ( int i = 63; i > 0; i-- ) {
    printf( "%d", ( ( v2 >> i ) & 1 ) );
}
printf( "\n" );

It turns out v1 is correct, but v2 is 0b010000111110000000000000000000000000000000000000000000000000000.

Could anyone be so kind to teach what happens here?

Also, I was wondering if C standard offers any way of printing out underlying representation of binary or hex, such that my print scheme can be replaced by an one-line function call?


Solution

  • In the first case

    signed long long v1 = (signed long long)(x);
    

    the compiler performs conversion from double to signed long long.

    In the second case

    signed long long v2 = *(signed long long *)(&x);
    

    the compiler interprets the internal representation of stored double as an object of the type signed long long.

    Pay attention to that float numbers are internally stored in special formats.

    From the C23 Standard Draft n3088:

    2 The following parameters are used to define the model for each floating type:

    s sign (±1)

    b base or radix of exponent representation (an integer > 1)

    e exponent (an integer between a minimum emin and a maximum emax)

    p precision (the number of base-b digits in the significand)

    fk nonnegative integers less than b (the significand digits)

    For each floating type, the parameters b, p, emin, and emax are fixed constants.

    As for your last question then if I am not mistaken then in the C23 Standard there is introduced conversion specifier b that allows to output integer numbers in a binary representation.

    As for C++ then starting from the C++20 Standard you can use format specifier b or B inside format output (see the description of the header <format>)