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?
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>
)