I defined two variables:
uint8_t a[2];
uint16_t b;
Next I want to use a
as variable of type uint16_t
, e. g.
b = (uint16_t)a;
But this is wrong! My programs doesn't works correctly with such code. All is OK when I replace b
to uint8_t b[2]
and use elementwise operations.
Why?
Best Answer
a
is a pointer to an array of bytes. If you cast it to a uint16_t and assign it tob
, thenb
will contain the address of the base of the array (where it is stored) in SRAM. If you want to treat the two bytes of the arraya
as an integer, then use a union as suggested by user14284, but be aware that the union will represent the byte array in the memory byte ordering of the architecture (in AVR that would be little-endian, which means byte 0 is the least significant byte). The way to write that in code is:Another way to do this without using a union is to cast
a
to a uint16_t pointer and then dereference it like so:If you are using the buffer to store big endian data (e.g. network byte order), then you'll need to byte-swap to use either of these techniques. A way to do that without any branches or temporary variables is:
Incidentally this is not an AVR or even an embedded-only problem. Application level networking code written for PCs typically calls functions called
htonl
,htons
(host to network, 32- and 16-bit variants) andntohl
,ntohs
(network to host, 32- and 16-bit variants) whose implementations are target architecture dependent as to whether they swap the bytes or not (under the assumption that bytes as transmitted 'on the wire' are always big-endian when they are part of multi-byte words).