Can this potentially cause undefined behaviour?
uint8_t storage[4];
// We assume storage is properly aligned here.
int32_t* intPtr = new((void*)storage) int32_t(4);
// I know this is ok:
int32_t value1 = *intPtr;
*intPtr = 5;
// But can one of the following cause UB?
int32_t value2 = reinterpret_cast<int32_t*>(storage)[0];
reinterpret_cast<int32_t*>(storage)[0] = 5;
char
has special rules for strict-aliasing. If I use char
instead of uint8_t
is it still Undefined Behavior? What else changes?
As member DeadMG pointed out, reinterpret_cast
is implementation dependent. If I use a C-style cast (int32_t*)storage
instead, what would change?
The pointer returned by placement new can be just as UB-causing as any other pointer when aliasing considerations are brought into it. It's your responsibility to ensure that the memory you placed the object into isn't aliased by anything it shouldn't be.
In this case, you cannot assume that
uint8_t
is an alias forchar
and therefore has the special aliasing rules applied. In addition, it would be fairly pointless to use an array ofuint8_t
rather thanchar
becausesizeof()
is in terms ofchar
, notuint8_t
. You'd have to compute the size yourself.In addition,
reinterpret_cast
's effect is entirely implementation-defined, so the code certainly does not have a well-defined meaning.To implement low-level unpleasant memory hacks, the original memory needs to be only aliased by
char*
,void*
, andT*
, whereT
is the final destination type- in this caseint
, plus whatever else you can get from aT*
, such as ifT
is a derived class and you convert that derived class pointer to a pointer to base. Anything else violates strict aliasing and hello nasal demons.