Is there a way to type-pun that is valid in both C and C++? Preferably low overhead, and avoiding trivial preprocessor hacks.
In C89, I know I can do something like this:
unsigned int float_bits(float num) {
return *(unsigned int *)#
}
However this violates C99's strict aliasing rule. So something like this might be more portable across the various C standards:
unsigned int float_bits(float num) {
union { float f; unsigned int i; } u;
u.f = num;
return u.i;
}
But I know that this is not valid C++, because only one member of a union can be “active” at a time. The typical solution given for both C and C++ is something like this:
unsigned int float_bits(float num) {
unsigned int i;
memcpy(&i, &num, sizeof(int));
return i;
}
However, this relies on the compiler being able to optimize away the call to memcpy. Is memcpy the only method that is portable across C and C++ standards?
(unsigned int *)&num
is not reliable. – Gemotmemcpy
is the way to go here. Or just don't do type punning, it's rarely needed :) – Tobimemcpy
is the only way, we can use this question as the canonical duplicate for all future questions of this type. – Ghassanmemcpy
any more (or less) reliable than using(unsigned int *)&num
? (Both will fail ifsizeof(float) != sizeof(int)
.) – Externalizesizeof(float) == sizeof(int)
then*(unsigned int *)#
is UB.memcpy
is valid in this case and astatic_assert
can be used to check the sizes match. – Ghassan* (unsigned int *) &num
would violate C’s rule about aliasing: The compiler is entitled to assume that an access via anunsigned int *
does not access an object that was defined asfloat
, regardless of the casts. When it optimizes, code such asnum = 4; * (unsigned int *) &num = 0; printf("%d\n", num); printf("%d\n", num);
could print “4” and “0”, or “4” and “4”, or “0” and “0”, among other things. – Bulldogunsigned char*
, but how do you get any other type of value out of it? It sounds like you’ll just end up implementingmemcpy
yourself. – Brandeschar *
– PlatinumT
is alwaysT
regardless of memcpying – Masao