What are the cases where reinterpret_casting 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, just- reinterpret_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 - intstart? Is it with the declaration of- data? If so, when does the lifetime of- dataend?
- What if - datawere 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?
 
     
     
    