long和char []的联合,字节顺序

时间:2012-01-19 02:04:36

标签: c endianness unions

如果我在8位处理器的代码中执行以下操作:

typedef union
{
unsigned long longn ;
unsigned char chars[4];
} longbytes;

longbytes.chars[0]总是会成为longbytes.longn的最低字节,还是依赖于字节序/编译器/平台/目标/运气等?我已经查看了我的编译代码的反汇编,这就是我在特定情况下的情况,但我很好奇这段代码是否可移植。

4 个答案:

答案 0 :(得分:7)

有几个原因导致无法携带:

  • 这取决于您的平台(或编译器)强制执行首先写入哪个字节的字节顺序,因此您不能指望chars[0]寻址最低字节
  • unsigned long不能保证与4字符一样长,因此根据平台,您甚至可能无法获得完整的long(或sizeof(long} )可能比4更小,你可以进一步阅读,但至少对8Bit处理器不太可能。
  • 读取一个不同的联盟成员然后你写的通常是不可移植的,它是实现定义的行为。其原因基本上是两个其他问题的结合。

总而言之,这些代码根本不可移植。

答案 1 :(得分:4)

一般情况下,如果你需要关心字节序,那么你做错了什么,需要解决你的问题(例如使用移位和掩码,或序列化/反序列化)。

例如,你可以做类似的事情而不是联盟,而不是:

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));
}

答案 2 :(得分:1)

这取决于平台如何在内部存储long。写入联合的一个元素然后从另一个元素中读取是不可移植的。

答案 3 :(得分:1)

union数据结构是可移植的,只要您不通过写入其中一部分并从另一部分读取而导致未定义的行为。具体而言,写入unsigned long并从unsigned char[4]读取或反之亦然是未定义的行为。