Ryan
Ryan

Reputation: 112

Reliable type-punning across C and C++ standards

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?

Upvotes: 6

Views: 279

Answers (1)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275385

unsigned int float_bits(float num) {
  unsigned int i;
  memcpy(&i, &num, sizeof(int));
  return i;
}

there is no side effect from that call of memcpy other than changing i to have the same bytes as num did.

It is true that compilers are free to insert a call to a library memcpy function here. They are also free to insert 1 million NOOPs, a pong simulation AI training session, and try to seach the proof space for the goldblach's conjecture proof.

At some point you have to presume your compiler isn't hostile.

Every decent compiler understands what memcpy does.

Upvotes: 7

Related Questions