结构体与位域的对齐

C结构体和C++中的类极为相似 它也可以有构造和析构函数以及其他成员函数 成员函数也通过一个隐含的this指针来操作类成员 它们之间唯一的区别就是默认的成员访问权限 类是私有 结构体是公有 以下对结构体的对齐操作等 大多数也对C++类适用

     结构体的对齐方式;
          1.对于结构体中的成员 每一个成员的地址必须是该成员类型大小的整数倍
          如
          
          
          编译器这样对齐是为了能够更高效率的传输数据 但是这样也会有一些问题 比如我们将结构体里的数据不变
      但是改变它们的顺序:
         
          此时结构体的大小变为了8 比前面节省了四个字节 也就是说结构体中的成员按照类型从小到大的序列是最好的 可惜编译器不会为我们做这些 
          结构体成员的对齐方式使得我们在使用时要注意以下几点:
               同一个结构体成员定义顺序不同 得到的大小可能不同
               结构体中中的成员有自己的对齐方式 因此我们不应该有通过*(&(s.a)+1)来访问b等类似的操作
               如果结构体ST含有静态成员 那么静态成员长度将不包含在sizeof(s)中 (类似C++中静态成员属于类)
     2.结构体的对齐方式,结构体的对齐字节就是结构体中最长的成员类型长度
               如对于上面定义的ST 它按照四个字节对齐
               又如:
     
          
          ST按照其中类型最长的double8字节对齐 这可以在STT中验证(stt.s1地址最后一位为0 是8的倍数) 
          STT包含ST STT的类型对齐将按照结构体ST的对齐方式 即也为8字节 可以在STTT中验证(&sttt.s2最后一位为8)
          另外 对于空结构体 它也要占用一个字节的内存 因为编译器要确保每一个结构体都有唯一的地址 注意这一个字节的空间在栈中由于栈本身的对齐方式 将占用四个字节

     位域:
          位域是指为位为单位来定义某结构体的成员变量 它和结构体是分不开的
          
           可见 a b c三个位段共用一个地址 但是变量i仍然其类型int的对齐方式 abc一共9位 剩余的23位并未使用
          位域的一些使用:
          1.位域变量仅限整型
          2.位域变量的长度不能够超过其本身类型的长度
          3.如果某一位域要从一个新的类型对齐处开始 可以在前面加一个长度为0的匿名位域 unsigned :0
          4.匿名位域长度不为0时 只起占位的作用
          5.一个位域必须容纳在同一个其类型对齐长度内
          关于位域对齐更多资料(网上摘录):


          /*************************************************************************

                    C99规定int、unsigned int和bool可以作为位域类型,但编译器几乎都对此作了扩展,
                    允许其它类型类型的存在。
                    使用位域的主要目的是压缩存储,其大致规则为:
                    1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof大小,则后面的字段将紧邻前一个字段存储,直到不能容纳为止;
                    2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof大小,则后面的字段将从新的存储单元开始,其偏移量为其类型大小的整数倍;(经测试此条好像仅限于char型,整型可以跨域存储)
                    3) 如果相邻的位域字段的类型不同,则各编译器的具体实现有差异,VC6采取不压缩方式,Dev-C++采取压缩方式;
                    4) 如果位域字段之间穿插着非位域字段,则不进行压缩;
                    5) 整个结构体的总大小为最宽基本类型成员大小的整数倍。
***************************************************************************/

               struct s1 
               { 
               int i: 8; 
               int j: 4; 
               int a: 3; 
               double b; 
               }; 

               struct s2 
               { 
               int i: 8; 
               int j: 4; 
               double b; 
               int a:3; 
               }; 

               printf("sizeof(s1)= %d\n", sizeof(s1)); 
               printf("sizeof(s2)= %d\n", sizeof(s2)); 
               result: 16, 24 
               第一个结构体中,i,j,a共占15个位,不足8个字节,按double 8字节对齐,共16字节

       第二个结构体中,i,j共占12位,不足8字节,按8字节对齐,a也按8字节对齐,加上double共8+8+8=24个字节

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值