I am confused as to how, endianness swaps the ordering of elements of a uint32_t
array when converted to a uint64_t
and vice-versa.
If I'm dealing with bytes stored in a uint8_t array of 8 elements, if I directly convert it to a uint64_t
using pointer casting and dereference like this:
uint8_t array[8] = {0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0xb0, 0xa0};
uint64_t u = *(uint64_t *)array;
On a little endian system, u
would be equal to 0xa0b0ffeeddccbbaa
But, if I have a uint32_t
array like this:
uint32_t arr[2] = {0xaabbccdd, 0xeeffb0a0} ;
uint64_t U = *(uint64_t *)arr;
On a little endian system, U
becomes 0xeeffb0a0aabbccdd
I intuitively understand the former case, but the latter, with the uint32_t
is confusing!
I have trouble visualizing the memory layout, during conversion, in the latter case...
Every help, will be greatly appreciated!
Endianess applies individually on every integer of 16 bits or larger. That is, on a little endian machine, a 32 bit integer 0xaabbccdd
is stored as dd cc bb aa
.
So an array of two 32 integers uint32_t [2]
with the values 0x11223344
and 0x55667788
are stored as
44 33 22 11
and 88 77 66 55
respectively. In an array, items are guaranteed to get stored contiguously, so in this case the memory will look like 44 33 22 11 88 77 66 55
.
A 64 bit integer 0x1122334455667788
is however stored as 88 77 66 55 44 33 22 11
, because again, endianess applies individually to each integer. This is why you can't re-interpret the memory layout of two 32 bit integers as a 64 bit integer on little endian machines.
If the CPU had been big endian however, the uint32_t [2]
would have been stored as:
11 22 33 44 55 66 77 88
and then it happens to get the same representation as a uint64_t
with the value 0x1122334455667788
.
As a sidenote, the *(uint64_t *)array
conversions in your code are undefined behavior because they violate strict pointer aliasing and could possibly also give misalignment. To convert between different memory types safely, you need to use bit shifts, memcpy
or union
.