大小端模式与位字段小总结

 最近看代码,突然看到以下的,当时就震惊了,除了MFC的一些,还是第一次看到类里定义牵扯到宏的。   加上以前对大小端和位字段的接触都很少,只是看到,然后粗看,飘过那种,想不到还真遇到了,于是总结下。
class DownlinkControlField {

public:
#if defined(__BIG_ENDIAN_BITFIELD)
    unsigned short res1:2;
    unsigned short ack:2;
    unsigned short res2:2;
    unsigned short dir:1;
    unsigned short sof:1;
    unsigned short mf:1;
    unsigned short packet_type:2;
    unsigned short transparent:1;
#elif defined (__LITTLE_ENDIAN_BITFIELD)
    unsigned short ack:2;
    unsigned short res1:2;
    unsigned short transparent:1;
    unsigned short packet_type:2;
    unsigned short mf:1;
    unsigned short sof:1;
    unsigned short dir:1;
    unsigned short res2:2;
#endif
};

     

一、大小端

        简而言之,大端是高对低,小端是高对高。后来一搜,说是大小端,居然是有个故事的。格列佛游记里一个故事,小人国的领导下了一道命令,规定人民在剥鸡蛋时必须从小的一段(little-end)开始。这规定惹恼了一群觉得应该从大端(big-end)开始剥的人,后来演变成纷争。支持little-end的人称为little-endian,支持big-end的人称为bid-endian。(来自http://bbs.c114.net/viewthread.php?tid=376162

        这样就好理解了,大端就是先放高位,放在低地址,小端就是先放小的,放在低地址。其实老外还是蛮有意思的。关于大小端讲的蛮不错的一篇文章http://my.oschina.net/alphajay/blog/5478?from=rss

大小端定义的头文件,在楼主ubuntu下为/usr/include/linux/typeoders目录下,一个little_endian.h一个big_endian.h;在楼主的vc6头文件中还有一个,C:\Program Files\Microsoft Visual Studio\VC98\Include目录下,endian.h。编译记得加上-D选项,如-D__LITTLE_ENDIAN_BITFIELD

有时候面试题会考到大小端的判断。应用到union的特性:union存储时,所有成员共用一个存储空间;union的存放顺序从低地址开始。于是如果判断cpu是大小端的c程序如下:       

 /*return 1 : little-endian, return 0:big-endian*/
int checkCPUendian(){
union {
unsigned int a;
unsigned char b;            
}c;
c.a = 1;
return (c.b == 1);      

}  
二、位字段

在存储空间宝贵的情况下,有时候需要将多个对象保存在一个机器字中。通常的方法是定义一个与相关位的位置对应的屏蔽码集合,如

#define  KEYWORD 01
#define  EXTERNAL 02
#define  STATIC      04

        这样,访问这些位就变味了移位运算、屏蔽运算以及补码运算等。尽管这方法简单可行,不过C语言还提供了另一种可替代的方法,来直接定义和访问一个字中的位字段的能力,不需要按位逻辑运算。       

struct bytedata
   {
         unsigned a:2;   /*位段a,占2位*/
         unsigned:6;     /*无名位段,占6位,但不能访问*/
         unsigned:0;     /*无名位段,占0位,表下一位段从下一字边界开始*/
         unsigned b:10; /*位段b,占10位*/
         int i;               /*成员i,从下一字边界开始*/
    } data;
对于位字段,需要注意以下:

1)一个字段必须存储在同一存储单元(word)中,不能跨越2个单元。如果单元空间不够,则剩余空间不用,从下月单元开始存放。

2)字段的所有属性几乎都有具体实现有关(所以才有如上的大小端下不同 的情况)

3)特殊宽度0可以用来强制在下一个字边界上对齐

4)无名字段(只有一个冒号和宽度)起填充作用(感觉像哑元素?)

5)字段不是数组,且没有地址,所以不能用&符号

6)字段可以仅仅声明为int,为方便移植,需要显式声明该int为signed还是unsigned类型。

7) 位段名不是变量名,比如首先int i:3,再int j:5,并不是在2个单独int中,所以在计算sizeof结构体的时候注意下

以前总觉得好多面试题钻的方向挺诡异的,现在才发现,的确是应用到了一些工程的实践啊,只是敲点小代码玩,的确没这个需求

参考网址:http://www.cnblogs.com/xiaoliyu/archive/2008/11/18/1335711.html

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值