#define ReinterpretDoubleAsUint64_t(x) ((union { double d; uint64_t u; }) { x } .u)
#define ReinterpretUint64_tAsDouble(x) ((union { uint64_t u; double d; }) { x } .d)
In C, code “(type) { initializer-list }” is a compound literal. It creates an object with the specified type and initialization. So:
(union { double d; uint64_t u; }) { x }
creates a union that is initialized with x
. By default, the first member of the union is initialized, so this is a union in which the double
member d
has been set to x
. Give that union, .u
is simply the usual way of referring to a member of a union. So:
(union { double d; uint64_t u; }) { x } .u
is the member u
of the union. When a union member other than the last one stored is read, the bytes of the union are reinterpreted in new type. So this reinterprets the bytes of the double
as uint64_t
.
This is standard C, but it uses implementation-defined behavior (notably, the way double
values are encoded depends on the implementation, as does whether double
and uint64_t
have the same size).