/*移位操作和大小端*/
无论大端还是小段,描述位操作(如,左移、右移都遵循这个一个概念:bit0 ---> bit7是从右向左的,如下示意图:
                            bit7   bit6   bit5  bit4   bit3   bit2   bit1   bit0
并且,移位操作发生在寄存器中,和大小端无关,大小端只和存储有关。举个例子:
对于 0x1234, 不管是大端还是小端设备,寄存器中的数据都是0x1234,不会改变,位移不会影响


大端系统字节增长方向和位域增长方向是一致的(可以参考RFC791中对ip头域的定义,以及linux kernel中对struct iphdr的定义)
byte:  |    0    |     1     |     2     |     3     |
bit:   0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7 0 1 2 3 4 5 6 7     LSB -> MSB 从左往右

小端系统则是这样的:
byte:  |    0    |     1     |     2     |     3     |
bit:   7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0 7 6 5 4 3 2 1 0      LSB -> MSB 从右往左

我们在代码中定义了位域,则位域都是从bit0 ---> bit7分配的(编译器都是这么定的吧...)。

比如定义了如下位域数据结构:
struct test
{
   char    a:1;
   char    b:2;
   char    c:3;
   char    d:2;
};

如上述结构体,如果定义在大端系统,则它在内存中的分布如下:
           bit  7  6  5  4  3  2  1  0
               d  d  c  c  c  b  b  a   == 0b abbcccdd

如果是在小端系统中定义,则它在内存中的分布如下:
           bit  7  6  5  4  3  2  1  0
               d  d  c  c  c  b  b  a    == 0b ddcccbba
所以对于同一个结构要在不同的大小端系统上通用,定义的时候,要分大小端来区分,参考linux kernel中对iphdr的定义:
struct iphdr {
#if defined(__LITTLE_ENDIAN_BITFIELD)
__u8 ihl:4,
version:4;
#elif defined (__BIG_ENDIAN_BITFIELD)
__u8 version:4,
  ihl:4;
#else
#error "Please fix "
#endif
__u8 tos;
__be16 tot_len;
__be16 id;
__be16 frag_off;
__u8 ttl;
__u8 protocol;
__sum16 check;
__be32 saddr;
__be32 daddr;
/*The options start here. */
};