Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 614
Ryan Avella Avatar asked Nov 02 '19 19:11

Ryan Avella


People also ask

What is type punning in C/C++?

In C and C++, constructs such as pointer type conversion and union ... are provided in order to permit many kinds of type punning, although some kinds are not actually supported by the standard language. Type aliasing or punning is when an object is referred to using different types, which may or may not be "compatible".

Why is type punning so dangerous?

This kind of type punning is more dangerous than most. Whereas the former example relied only on guarantees made by the C programming language about structure layout and pointer convertibility, the latter example relies on assumptions about a particular system's hardware.

What is type punting in C and C++?

In C and C++, constructs such as pointer type conversion and union — C++ adds reference type conversion and reinterpret_cast to this list — are provided in order to permit many kinds of type punning, although some kinds are not actually supported by the standard language.

What is type punning in sockets programming?

In other words, the sockets library uses type punning to implement a rudimentary form of polymorphism or inheritance . Often seen in the programming world is the use of "padded" data structures to allow for the storage of different kinds of values in what is effectively the same storage space.


1 Answers

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.

like image 51
Yakk - Adam Nevraumont Avatar answered Oct 17 '22 17:10

Yakk - Adam Nevraumont