Каковы случаи, когда reinterpret_cast
ing a char*
(или char[N]
) - это поведение undefined, и когда это определено поведение? Каково правило, которое я должен использовать, чтобы ответить на этот вопрос?
Как мы узнали из этого вопроса, следующее поведение undefined:
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
Но в какой момент мы можем сделать reinterpret_cast
в массиве char
и не иметь это поведение undefined? Вот несколько простых примеров:
-
Нет
new
, просто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?
Когда начинается время жизни для
int
? Это с объявлениемdata
? Если да, то когда заканчивается время жизниdata
? -
Что делать, если
data
был указателем?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?
-
Что делать, если я просто получаю структуры на проводе и хочу условно отбросить их в зависимости от того, что такое первый байт?
// 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; // ... }
Есть ли какой-либо из этих случаев UB? Все ли они? Изменяется ли ответ на этот вопрос между С++ 11 и С++ 1z?