C语言的位域,字节对齐.doc_第1页
C语言的位域,字节对齐.doc_第2页
C语言的位域,字节对齐.doc_第3页
C语言的位域,字节对齐.doc_第4页
免费预览已结束,剩余1页可下载查看

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C的位域(bit fields )C语言位域的最大作用是简化位操作,可以让开发者以直观的方式来操作某一位.如下列定义struct bsint a:7;int b:2;int c:1;表示用一个整数的前8位表示a,用一个整数的2位表示b,用一个整数的1位的来表示c,位域定义不能超过数据定义类型的最大位,如struct char a:9; /char 最大值为8位int b:33; /int 的最大值为32,不能超过其中定义值位域有如下特殊定义,1) 只要不超过数据定义最大值,多个位域可以定义一个数据单位里,如下是合法,定义,也是常用定义Struct PC_PINChar bit0:1,bit1:1, Bit2:1, Bit3:1, Bit4:1, Bit5:1, Bit6:1, Bit7:1; 2) 位域可以采用匿名,定义,这样程度就不能使用这些位,这样定义纯粹是起占位用.struct foo1 inta : 1;int : 2;shortc : 1;上例中,在a和c中有一个2位的匿名占位struct bsunsigned a:4unsigned :0 /*空域*/unsigned b:4 /*从下一单元开始存放*/unsigned c:4在这个位域定义中,a占第一字节的4位,后4位填0表示不使用,b从第二字节开始,占用4位,c占用4位。位域占位计算有点复杂1. 定义位域不足一个数据位的,按一个完整数据算 Struct tagA Int a:3; Int b;Sizeof()值是 8,因为a仍然按4位来核算.2. 如果连续定义几点相同类型.而位域总合不超过类型总位数长度的,会被编译器设为一个合并为一个位域定义如struct tagAint a:1;int b:2;int c;3等同于 struct tagB Int a:1, b:2, c:3; ;Sizeof()的长度都是4,因为tagA的各个成员加起长度都没有超过32,所以仍然为43. aaa 位域的被广泛应用于8位单片机编程中.因为一个8位寄存器刚好是一个char 的宽度,因为可以定义一个8个位位域来对寄存器的各个位进行存取.这样程序比较简单并且好理解.但在32位CPU应用反而不广泛,因为32CPU的寄存器是为32位宽度,正好是一个int 的宽度,但int在不同CPU中的表示顺序位是不一致的.在不同字节序CPU里定义的位域,有一些不样,换句话说,定义这样位域需要定义两套类型.如ip的头定义.以下取自 Linux 中,linux/ip.hstruct iphdr #if defined(_LITTLE_ENDIAN_BITFIELD)_u8ihl:4,version:4;#elif defined (_BIG_ENDIAN_BITFIELD)_u8version:4, ihl:4;#else#errorPlease fix #endif_u8tos;_u16tot_len;_u16id;_u16frag_off;_u8ttl;_u8protocol;_u16check;_u32saddr;_u32daddr;/*The options start here. */;使用反而不如位操作定义方便,因此32位CPU使用位域有一些麻烦 字节对齐现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但为为了CPU访问数据的快速,通常都要求数据存放的地址是有一定规律的.比如在32位CPU上,一般要求变量地址都是基于4位,这样可以保证CPU用一次的读写周期就可以读取变量.不按4位对齐,如果变量刚好跨4位的吗,这样需要CPU两个读写周期.效率自然低下.因此,在现代的编译器都会自动把复合数据定义按4位对齐,以保证CPU以最快速度读取,如下例(gcc version 3.2.2编译器(32位x86平台))struct A int a; char b; short c;结构体A中包含了4字节长度的int一个,1字节长度的char一个和2字节长度的short型数据一个。所以A用到的空间应该是7字节。但是因为编译器要对数据成员在空间上进行对齐。所以使用sizeof(strcut A)值为8。现在把该结构体调整成员变量的顺序。struct B char b; int a; short c;这时候同样是总共7个字节的变量,但是sizeof(struct B)的值却是12,因为b+a 已经超过32,编译无法合并在一个空间,干脆分配了4个byte空间.但这样分配空间一个不好结果就是,各个成员的相对起移地址,的位移是不确定的.在不同CPU的有不同结果.这样对于经常处理网络包的嵌入式C程序员是一个大问题如下例,假设某人设计不一不按4位对齐的包协议,如下 前一个1 位表示版本号,第2-5位表示,包序号,第6-7位表示端口号.这时发来一个网络包 0x01,0x12,0x23,0x10,0x10,0xFF,0xFF如果你设计一个结构,去记取Struct protocolChar version;Int serialno;Short port;用这个结构去强制读取前面包buffer,会得出一个错误的结果!,包的serial 号和port 号都不会取到 0x10101223和0xFFFF.为什么?因为编译器已经把这个结构优化,造成包结构成员的相对位移发生变化.对应位的值就不是原来的值.为此,有必要告诉编译器,我这个结构是不需要进行字节对齐优化的.在不同编译器,有不同方法来优化.一般是采用#pragma pack (n) 编译指令来告诉编译器,后面的结构采用n字节对齐,如果n=1表示,不对齐,强制要原始地址排列.网络包通常需要这样定义用#pragma pack () 取消上一次字节对齐指令,恢复成缺省对齐编译.#pragma pack (2) /*指定按2字节对齐*/struct C char b; int a; short c;#pragma pack () /*取消指定对齐,恢复缺省对齐*/在gcc 还有一种特殊编译属性_attribute_(packed),可以强制让结构不对齐,即采用1字节对齐模式.以

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论