您当前的位置: 首页 > 

phymat.nico

暂无认证

  • 1浏览

    0关注

    1967博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

结构体与位域的对齐

phymat.nico 发布时间:2017-12-19 22:41:33 ,浏览量:1

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个字节
关注
打赏
1659628745
查看更多评论
立即登录/注册

微信扫码登录

0.0446s