Jakie są przypadki, w których reinterpret_cast
ing char*
(lub char[N]
) jest niezdefiniowanym zachowaniem, a kiedy jest to zdefiniowane zachowanie? Jaka jest reguła, z której powinienem skorzystać, aby odpowiedzieć na to pytanie?reinterpret_cast, char * i niezdefiniowane zachowanie
Jak dowiedzieliśmy się od this question następujące zachowanie jest niezdefiniowane:
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
Ale w którym momencie możemy zrobić reinterpret_cast
na char
tablicy i go NIE niezdefiniowane zachowanie? Oto kilka prostych przykładów:
nr
new
tylkoreinterpret_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?
Kiedy robi życia na początku
int
? Czy jest to z deklaracjądata
? Jeśli tak, kiedy kończy się żywotnośćdata
?Co jeśli wskaźnik myszy byłby
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?
Co jeśli mam tylko odbieranie konstrukcjom na drucie i chcą rzucić je warunkowo na podstawie tego, co pierwszy bajt jest?
// 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; // ... }
Czy któryś z tych przypadków UB? Czy to wszystko? Czy odpowiedź na to pytanie zmienia się między C++ 11 na C++ 1z?
** (1) ** wygląda na ważny dla mnie. W obu instrukcjach tworzony jest nowy obiekt 'int' i przypisywana jest jego wartość. * Czytanie * to wartość, w której wszystko zaczyna się robić włochate. To samo z ** (2) ** (przy założeniu 'sizeof (int) == 4'). ** (3) ** dla mnie wygląda jak UB. –
@IgorTandetnik Rozwiązałem pytania również z pewnym odczytaniem i pozbyłem się założenia dotyczącego 'sizeof (int)', dziękuję. – Barry
Teraz ** (1) ** i ** (2) ** wydają się wykazywać UB, na tych samych podstawach co połączone pytanie. Byłoby łatwo uratować, zapisując wskaźnik od pierwszego rzutu i używając go do wszystkich kolejnych zapisów i odczytów. –