Type punning in modern C++ - Timur Doumler - CppCon 2019
Why Stack Overflow recommends it
Stack Overflow users link it when answering questions about undefined behaviour in unions, pointer casts and byte-buffer reinterpretation, as the definitive explanation of what is and isn't legal.
Recommended by 8 people across 8 different months, 2019 to 2023.
What it is
A one-hour CppCon 2019 talk by Timur Doumler, an ISO C++ committee member, surveying type punning in C++: unions, reinterpret_cast, memcpy and C++20's std::bit_cast. It covers object lifetime, aliasing rules, value representations, language holes and proposals to fix them.
What people said
Strong rec Valeriy Savchenko · 2019-12 · Stack Overflow · on “A case of undefined behaviour when using a union”
I would recommend watching this CppCon video: [this video] The speaker explains everything with great attention to the detail and proposes more modern solutions.
Strong rec Konrad Rudolph · 2021-04 · Stack Overflow · on “What does a cast from byte buffer to a struct do?”
@JeremyFriesner Yep, that’s currently also UB. Here’s the paper: [LINK] If you’re curious about the low-level details of this, Timur’s talk is a must-watch: [this video]
Recommends Nick · 2019-10 · Stack Overflow · on “C++ type punning via fallback to C”
I watched this excellent video [this video] I wonder if we can do this instead of strange memset hack: [LINK] struct S{ int a; }; extern "C"{ static void fix(S *s){ int *x = (int *) s; *x = 5; } } int main(){ S s; fix(&s); return s.a; } This fallback to C seems to be completely legal? (please do not comment that this kind of type punning is legal in C++11 and above)
Recommends DBS4261 · 2020-02 · Stack Overflow · on “Cuda type punning - memcpy vs UB union”
So I was curious about this and took a look in compiler explorer [LINK] It seems that cuda does the full memcpy. There is no general reccomendation but we can learn something from the c++20 standard with std::bit_cast. I think taking the implementation of std::bit_cast and change the guts to have a reinterpret cast is the best way forward. It is still undefined behavior but you are compiling for a single architecture, so it will at least be consistently undefined. And it adds a lot of idiotproofing that the undefined behavior route allows. template <class To, class From, class Res = typename std::enable_if< (sizeof(To) == sizeof(From)) && (alignof(To) == alignof(From)) && std::is_trivially_c
Recommends JMC · 2020-09 · Stack Overflow · on “Can you access the object representation of any object through a char*?”
This video [this video] , linked in the comments (now chat) by @KonradRudolph is likely the answer to the problem. At around the 40min mark, Timur Doumler, who is a member of the ISO C++ commitee, discusses the possibility of accessing byte representations. The summary is that any attempt of accessing byte representation except memcpy is UB. The situation in the OP does not even arise without making use of UB because the very act of using a pointer to an object like an array, or doing any pointer arithmetic on it is UB, as these operations are only well-defined when dealing with actual array objects, as far as the abstract machine is concerned. Also, while reinterpreting a pointer as a char* does
Recommends Peter - Reinstate Monica · 2021-12 · Stack Overflow · on “In C or C++, is memory layout of uint64_t guaranteed to be the same as uint32_t[2] ? Can one be cast as the other?”
At least since C++20 there are no special integer values in C++ (as opposed to, I think, C, where they in theory still exist), and hence all bit combinations of two adjacent uint32 objects form a valid 64 bit integer bit sequence. Casting a pointer is still disallowed because of aliasing and potentially alignment issues, but in C++20 you can use std::bit_cast() to obtain a bit-wise copy of the original: uint32_t arr[2] = {}; uint64_t ui64 = std::bit_cast<uint64_t>(arr); . Note that this performs a copy. As Kamil said, the result may be surprising on a little endian system, but it is valid. There is an hour-long, medium interesting CppCon talk about type punning [this video] by Timur Doumler on yo
Recommends Ramon · 2022-07 · Stack Overflow · on “Typecast char array into a structure (not a class/object)”
This is the C answer. For C++ the more explicit way of doing it, which does exactly the same thing, is a *reinterpret_cast (byteArray); In most cases these two are equivalent but there are edge cases where a C-style cast might not do what you expect. Note that this is also undefined behavior. For a basic explanation of what the problem with this kind of type punning is and which kind of alternatives exist you might want to watch [this video]
Recommends catnip · 2023-12 · Stack Overflow · on “Can i use placement new as a bit_cast?”
What @Ayrter said, if you can use C++23, otherwise use std::bit_cast , the overhead of which, in your example certainly, is almost certainly zero. The optimiser will simply optimise the copy away (as I believe you now know). As for using placement new to re-use storage while retaining access to its contents, the standard does in fact call this out explicitly [LINK] : new (this) D2; // reuses storage --- ends the lifetime of this So there you have it. What you are proposing is UB. Interesting video on the whole subject of type punning here [this video] , although it is an hour long. It's taken the standards guys soooooooooooooo long to address this.
Cites Evg · 2019-10 · Stack Overflow · on “Can you std::bit_cast to a std::array to obtain the bytes of an object?”
In his recent talk “Type punning in modern C++” [this video] Timur Doumler said [this video] that std::bit_cast cannot be used to bit cast a float into an unsigned char[4] because C-style arrays cannot be returned from a function. We should either use std::memcpy or wait until C++23 (or later) when something like reinterpret_cast<unsigned char*>(&f)[i] will become well defined. In C++20, can we use an std::array with std::bit_cast , float f = /* some value */; auto bits = std::bit_cast<std::array<unsigned char, sizeof(float)>>(f); instead of a C-style array to get bytes of a float ?
Cites Daniel Stephens · 2019-10 · Stack Overflow · on “What happens if undefined C++ behaviour meets C defined behaviour?”
I can recommend this talk [this video] I am still not sure if it validates the answer, or if it is actually saying the opposite :-o C++ is a nightmare.. lol