KNfLrPn
KNfLrPn

Reputation: 1329

Union of long and char[], byte order

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

Answers (4)

Grizzly
Grizzly

Reputation: 20211

There are several reasons why this is not portable:

  • It depends on the endianess your platform (or compiler) enforces which byte is written first, so you can't count on chars[0] addressing the lowest byte
  • unsigned 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.
  • Reading a different union member then you wrote to is generally not portable, it is implementation defined behaviour. The reason for this is basically the combination of the two other issues.

So all in all that code is not portable at all.

Upvotes: 7

Brendan
Brendan

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

Sergey Kalinichenko
Sergey Kalinichenko

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

David Schwartz
David Schwartz

Reputation: 182827

It depends on how the platform stores longs internally. Writing to one element of a union and then reading from another is not portable.

Upvotes: 1

Related Questions