What are the cases where reinterpret_cast
ing a char*
(or char[N]
) is undefined behavior, and when is it defined behavior? What is the rule of thumb I should be using to answer this question?
As we learned from this question, the following is undefined behavior:
alignas(int) char data[sizeof(int)];
int *myInt = new (data) int; // OK
*myInt = 34; // OK
int i = *reinterpret_cast<int*>(data); // <== UB! have to use std::launder
But at what point can we do a reinterpret_cast
on a char
array and have it NOT be undefined behavior? Here are a few simple examples:
No
new
, justreinterpret_cast
:alignas(int) char data[sizeof(int)]; *reinterpret_cast<int*>(data) = 42; // is the first cast write UB? int i = *reinterpret_cast<int*>(data); // how about a read? *reinterpret_cast<int*>(data) = 4; // how about the second write? int j = *reinterpret_cast<int*>(data); // or the second read?
When does the lifetime for the
int
start? Is it with the declaration ofdata
? If so, when does the lifetime ofdata
end?What if
data
were a pointer?char* data_ptr = new char[sizeof(int)]; *reinterpret_cast<int*>(data_ptr) = 4; // is this UB? int i = *reinterpret_cast<int*>(data_ptr); // how about the read?
What if I'm just receiving structs on the wire and want to conditionally cast them based on what the first byte is?
// bunch of handle functions that do stuff with the members of these types void handle(MsgType1 const& ); void handle(MsgTypeF const& ); char buffer[100]; ::recv(some_socket, buffer, 100) switch (buffer[0]) { case '1': handle(*reinterpret_cast<MsgType1*>(buffer)); // is this UB? break; case 'F': handle(*reinterpret_cast<MsgTypeF*>(buffer)); break; // ... }
Are any of these cases UB? Are all of them? Does the answer to this question change between C++11 to C++1z?
See Question&Answers more detail:os