endianness for bit-fields

考虑下面的一个简单的C结构体:

struct {
    unsigned char a:4;
    unsigned char b:4;
}t1;

以前一直想当然的认为,编译器会把a安排在高4位,而b在低4位。不过在小端系统上,多数编译器是将b放在高4位的;而在大端系统上比较符合我的直觉,a在高4位。不过,这种安排并非是一标准,依赖于编译器的实现,不具备可移植性。因此,如果定义的数据结构是要跨大小端系统的,可以考虑通过位操作而非bit-fields来实现。且从汇编代码中亦可以看出,编译器其实也是通过位操作来支持bit-fields的。

那么下面这个结构呢?

struct {
    unsigned short a:4;
    unsigned short b:12;
}t2;

假设t2.a = 0xa; t2.b = 0xbcd,那么在小端和大端上的内存布局通常分别为:

小端:                    大端:
+--------+--------+    +--------+--------+
| d   a  |  b  c  |    | a   b  |  c  d  |
+--------+--------+    +--------+--------+

在小端上系统上,首先是b的低4位、加a的4位,然后是b的高8位。而在大端系统上,则首先是a的4位、加b的高4位,然后是b的低8位。可以看出,如果一个结构里有跨8bits的field,如果不进行字节序的转化,是不可能保存成平台无关的数据文件的。