reinterpret_cast, char * и неопределенное поведение
Каковы случаи, когдаreinterpret_cast
вchar*
(или жеchar[N]
) неопределенное поведение, и когда это определенное поведение? Какое эмпирическое правило я должен использовать, чтобы ответить на этот вопрос?
Как мы узнали изэтот вопрос, следующее неопределенное поведение:
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
массив и он НЕ будет неопределенным поведением? Вот несколько простых примеров:
нет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? Все ли они? Меняется ли ответ на этот вопрос между C ++ 11 и C ++ 1z?