c语言 ld字节,C语言的位域,字节对齐.doc

253b171540df25e1b84436cbe50dfc72.gifC语言的位域,字节对齐.doc

C的位域 bit fields C语言位域的最大作用是简化位操作 ,可以让开发者以直观的方式来操作某一位 .如下列定义 struct bs int a7; int b2; int c1; ; 表示用一个整数的前 8位表示 a,用一个整数的 2位表示 b,用一个整数的 1位的来表示 c, 位域定义不能超过数据定义类型的最大位 , 如 struct char a9; char 最大值为 8位 int b33; int 的最大值为 32,不能超过其中定义值 位域有如下特殊定义 , 1 只要不超过数 据定义最大值 ,多个位域可以定义一个数据单位里 ,如下是合法 ,定义 ,也是常用定义 Struct PC_PIN Char bit01, bit11, Bit21, Bit31, Bit41, Bit51, Bit61, Bit71; 2 位域可以采用 匿名 ,定义 ,这样程度就不能使用这些位 ,这样定义纯粹是起占位用 . struct foo1 int a 1; int 2; short c 1; ; 上例中 ,在 a和 c中有一个 2位的 匿名 占位 struct bs unsigned a4 unsigned 0 /*空域 */ unsigned b4 /*从下一单元开始存放 */ unsigned c4 在这个位域定义中, a占第一字节的 4位,后 4位填 0表示不使用, b从第二字节开始,占用 4位, c占用 4位。 位域占位计算有点复杂 1. 定义位域不足一个数据位的 ,按一个完整数据算 Struct tagA Int a3; Int b; ; Sizeof值是 8,因为 a仍然按 4位来核算 . 2. 如果连续定义几点相同类型 .而位域总合不超过类型总位数长度的 ,会被编译器设为一个合并为一个位域定义 如 struct tagA int a1; int b2; int c;3 等同于 struct tagB Int a1, b2, c3; ; Sizeof的长度都是 4,因为 tagA的各个成员加起长度都没有超过 32,所以仍然为 4 3. aaa 位域的被广泛应用于 8位单片机编程中 .因为一个 8位寄存器刚好是一个 char 的宽度 ,因为可以定义一个 8个位位域来对寄存器的各个位进行存取 .这样程序比较简单并且好理解 .但在 32位 CPU 应用反而不广泛 ,因为 32CPU 的寄存器是为 32 位宽度 ,正好是一个 int 的宽度 ,但 int在不同 CPU中的表示顺序位是不一致的 .在不同字节序 CPU里定义的位域 ,有一些不样 ,换句话说 ,定义这样位域需要定义两套类型 .如 ip的头定义 . 以下取自 Linux 中 ,linux/ip.h struct iphdr if definedLITTLE_ENDIAN_BITFIELD u8 ihl4, version4; elif defined BIG_ENDIAN_BITFIELD u8 version4, ihl4; else error “Please fix “ endif u8 tos; u16 tot_len; u16 id; u16 frag_off; u8 ttl; u8 protocol; u16 check; u32 saddr; u32 daddr; /*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 字节。但是因为编译器要对数据成员在空间上进行 对齐。 所以使用 sizeofstrcut A值为 8。 现在把该结构体调整成员变量的顺序。 struct B char b; int a; short c; ; 这时候同样是总共 7个字节的变量,但是 sizeofstruct B的值却是 12,因为 ba 已经超过 32,编译无法合并在一个空间 ,干脆分配了 4个 byte空间 . 但这样分配空间一个不好结果就是 ,各个成员的相对起移地址 ,的位移是不确定的 .在不同CPU的有不同结果 .这样对于经常处理网络包的嵌入式 C程序员是一个大问题 如下例 ,假设某人设计不一不按 4位对齐的包协议 ,如下 前一个 1 位表示版本号 ,第 2-5 位表示 ,包序号 ,第 6-7位表示端口号 . 这时发来一个网络包 0 x01,0 x12,0 x23,0 x10,0 x10,0 xFF,0 xFF 如果你设计一个结构 ,去记取 Struct protocol Char version; Int serialno; Short port; ; 用这个结构去强制读取前面包 buffer,会得出一个错误的结果 ,包的 serial 号和 port 号都不会取到 0 x10101223 和 0 xFFFF.为什么 因为编译器已经把这个结构优化 ,造成包结构成员的相对位移发生变化 .对应位的值就不是原来的值 . 为此 ,有必要告诉编译器 ,我这个结构是不需要进行字节对齐优化的 .在不同编译器 ,有不同方法来优化 . 一般是采用 pragma pack n 编译指令来告诉编译器 ,后面的结构采用 n 字节对齐 ,如果 n1表示 ,不对齐 ,强制要原始地址排列 .网络包通常需要这样定义 用 pragma pack 取消上一次字节对齐指令 ,恢复成缺省对齐编译 . pragma pack 2 /*指定按 2 字节对齐 */ struct C char b; int a; short c; ; pragma pack /*取消指定对齐,恢复缺省对齐 */ 在 gcc 还有一种特殊编译属性 attributepacked ,可以强制让结构不对齐 ,即采用 1字节对齐模式 . 以下是两种不对齐的方法 . 1 结构内部成员的 pack struct foo char a; int b attribute packed; ; 2 整个结构的 pack struct foo char a; int b; attribute packed;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值