位序浅析
下面咱们先看一下struct iphdr的定义,后文会解惑为何要在一个字节中区分大小端。.net
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 <asm/byteorder.h>"
#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. */
};
比特序(bit order)
字节序是一个对象中的多个字节之间的顺序问题,比特序就是一个字节中的8个比特位(bit)之间的顺序问题。通常状况下系统的比特序和字节序是保持一致的。
一个字节由8个bit组成,这8个bit也存在如何排序的状况,跟字节序相似的有最高有效比特位、最低有效比特位。
比特序1 0 0 1 0 0 1 0在大端系统中最高有效比特位为一、最低有效比特位为0,字节的值为0x92。在小端系统中最高、最低有效比特位则相反为0、1,字节的值为0x49。
跟字节序相似,要想保持一个字节值不变那么就要使系统能正确的识别最高、最低有效比特位。unix
直接上代码分析:
#include<stdio.h>对象
struct bit_order{
unsigned char a: 2,
b: 3,
c: 3;
};blog
int main(int argc, char *argv[])
{
unsigned char ch = 0x79;
struct bit_order *ptr = (struct bit_order *)&ch;排序
printf("bit_order->a : %u\n", ptr->a);
printf("bit_order->b : %u\n", ptr->b);
printf("bit_order->c : %u\n", ptr->c);ip
return 0;
}内存
liuxingen@ V6-Dev ~/station $ ./bitfiled
bit_order->a : 1
bit_order->b : 6
bit_order->c : 3
下面是hp-unix的运行结果
# ./bitfiled
bit_order->a : 1
bit_order->b : 7
bit_order->c : 1博客
内存图分析it
从上面的输出能够看到一样的代码在不一样的机器中输出了不一样的结果,也就是说咱们的代码在不一样的平台不能直接移植,致使这个问题的缘由就是咱们前面提到的关于位域的一个约定,定义在前面的位域老是出如今低地址的bit位中,由于不一样的平台的比特序是不一样的,可是咱们定义的位域没有根据平台的大小端进行转换,最后就致使了问题。那么如何解决这个问题,那就是在定义结构体中的位域时判断平台的大小端
代码改为以下就没有问题了
#include<stdio.h>
#include<asm/byteorder.h>io
struct bit_order{
#if defined(__LITTLE_ENDIAN_BITFIELD)
unsigned char a: 2,
b: 3,
c: 3;
#elif defined (__BIG_ENDIAN_BITFIELD)
unsigned char c: 3,
b: 3,
a: 2;
#else
#error "Please fix <asm/byteorder.h>"
#endif
};
int main(int argc, char *argv[])
{
unsigned char ch = 0x79;
struct bit_order *ptr = (struct bit_order *)&ch;
printf("bit_order->a : %u\n", ptr->a);
printf("bit_order->b : %u\n", ptr->b);
printf("bit_order->c : %u\n", ptr->c);
return 0;
}
到此咱们也就解释了文章开头关于struct iphdr定义中的那个疑问。
参考博客http://blog.csdn.net/liuxingen/article/details/45420455/