Reputation: 1329
If I do the following in code for an 8-bit processor:
typedef union
{
unsigned long longn ;
unsigned char chars[4];
} longbytes;
Is longbytes.chars[0]
always going to be the lowest byte of longbytes.longn
, or does it depend on endianness/compiler/platform/target/luck etc.? I've viewed the disassembly of my complied code and that's how it is in my specific case, but I'm curious if this code is portable.
Upvotes: 3
Views: 4558
Reputation: 20211
There are several reasons why this is not portable:
chars[0]
addressing the lowest byteunsigned long
is not guaranteed to be exactly as long as 4
chars, so depending on the platform you might not even get the complete long
(or sizeof(long
) might be smaller then 4
and you read further, but that's unlikely for 8Bit processors at least.So all in all that code is not portable at all.
Upvotes: 7
Reputation: 37222
In general, if you ever need to care about endianness you're doing something wrong, and need to work around your problem (e.g. with shifts and masks, or serialisation/de-serialisation).
For example, rather than having a union maybe you should do something like:
uint32_t pack(uint8_t byte0, uint8_t byte1, uint8_t byte2, uint8_t byte3) {
long result;
result = byte0;
result |= byte1 << 8;
result |= byte2 << 16;
result |= byte3 << 24;
return result;
}
uint8_t unpack(int byteNumber, uint32_t value) {
return (value >> (byteNumber * 8));
}
Upvotes: 5
Reputation: 726969
The union
data structure is portable as long as you do not cause undefined behavior by writing into one part of it and reading from the other. Specifically, writing to unsigned long
and reading from unsigned char[4]
or vice versa is undefined behavior.
Upvotes: 1
Reputation: 182827
It depends on how the platform stores long
s internally. Writing to one element of a union and then reading from another is not portable.
Upvotes: 1