According to the type aliasing rules, i assume that:
1) direct conversion of uint64_t*
to uint32_t*
- is incorrect (i can't access the data through the result ptr. and be sure i will get the correct value)
2) conversion chains is OK (i can safely access the data)
uint64_t* -> unsigned char* -> uint32_t*
uint64_t* -> void* -> uint32_t*
Am i understanding the rules correctly or not?
I'm always prefer to use unions instead, to prevent any possible ptr. conversion problems (which can cause data corruption), but it is not always possible (and good) solution.
2) conversion chains is OK (i can safely access the data)
uint64_t* -> unsigned char* -> uint32_t* uint64_t* -> void* -> uint32_t*
Am i understanding the rules correctly or not?
No. A chained reinterpret_cast
like that will not be any more correct than a direct reinterpret_cast
.
I'm always prefer to use unions instead
Type punning with a union also violates aliasing rules.
If you have a pointer to uint64_t
, and you want to use four of the eight bytes (I'm assuming a 8 bit byte) contained in the object and interpret them as a uint32_t
, then you must first decide on which of the eight bytes you want to use. After all, all eight of them won't fit in a single uint32_t
. Do you want the low order bytes, or the high order bytes? Or perhaps something more exotic, like every other byte? Also consider, in which order should the bytes be in the resulting uint32_t
.
If you want particular bytes based on their significance, then the portable way is to use bit shifts and masks.
If you want particular bytes based on their position in memory, then the portable way is to use std::memcpy
.