zoukankan      html  css  js  c++  java
  • 字节对齐《c和指针》笔记包含位域结构体的内存对齐(32bit,GCC)

    最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--字节对齐

        C99划定int、unsigned   int和bool可以作为位域类型。但编译器几乎都对此作了扩展,答应其它类型类型的存在。

        如果结构体中含有位域(bit-field),总结规则如下:(以下代码在x86 32bit系统上测试,gcc 4.1.2)

        1) 如果相邻位域字段的类型相同,且其位宽之和小于类型的sizeof巨细,则前面的字段将紧邻前一个字段存储,直到不能包容为止

        例:

        struct test1 {

        char    a : 2;

        char    b : 3;

        char    c : 3;

        };

        3个变量恰好占1个字节,所以整体只要占1个字节

        2) 如果相邻位域字段的类型相同,但其位宽之和大于类型的sizeof巨细,则前面的字段将从新的存储单元开始,其偏移量为其类型巨细的整数倍

        例:

        struct test2 {

        char    a : 2;

        char    b : 3;

        char    c : 7;

        };

        3个变量超过1个字节,a和b在占一个字节,c占一个字节,所以整体占2个字节。

        3) 如果相邻的位域字段的类型不同,则各编译器的详细实现有差异,VC6采用不压缩方法(不同位域字段存放在不同的位域类型字节中),Dev-C++和GCC都采用压缩方法

        例1:

        struct test3

        {

        char a:1;

        char b:1;

        long c:1;

        char d:2;

        };

        4个变量<=1个字节,所以整体占1个字节,对吧!

        错了,开始我也是这样想的,结果是4个。

        我猜想了一下:

        虽然a,b,c,d加起来只占1个字节,但是最后结构体整体也要停止对齐。

        详细可以查看之前写的不含位域的内存对齐说明http://blog.csdn.net/todd911/article/details/6528428,

        对齐规则的第二条:结构(或结合)的整体对齐规则:在 数据成员完成各自对齐之后,结构(或结合)本身也要停止对齐,对齐将按照#pragma pack指定的数值和结构(或结合)最大数据成员长度中,比较小的那个停止。

        每日一道理
    这浓浓的母爱使我深深地认识到:即使你是一只矫健的雄鹰,也永远飞不出母爱的长空;即使你是一条扬帆行驶的快船,也永远驶不出母爱的长河!在人生的路上不管我们已走过多远,还要走多远,我们都要经过母亲精心营造的那座桥!

        这边因为没有定义#pragma pack,所以默认按4个字节停止对齐,结构体中最大的数是long,占4个字节,所以最终要按4个字节停止整体对齐。

        我们来验证一下,如果将结构体改成:

        struct test3

        {

        char  a:1;

        char  b:1;

        short c:1;

        char  d:2;

        };

        结果应该是2。

        试一下,确实是2.

        再来修改一下:

        struct test3

        {

        char a:1;

        char b:1;

        long c:31;

        char d:2;

        };

        上面的结构体占12个字节。

        a,b合起来占1个字节,c如果要合到a,b中去,的话就是33bit,超过将按照#pragma pack指定的数值和结构(或结合)最大数据成员长度中,比较小的那个,

        所以c只能自立门户,从第5个字节(偏移量为32bit)开始放置占4个字节,同理最后d也合不进c中去,所以从第9个字节开始放置,最后结构体整体对齐,结果是12.

        总结gcc的压缩方法:

        a.先要取得#pragma pack指定的数值和结构(或结合)最大数据成员长度中,比较小的那个值,这边称为对齐基数。

        b.按照结构体中变量的次序,如果能合在一起且不超过a中的对齐基数的就合并,不能合并的需要自立门户,偏移量为对齐基数的整数倍,继续检查是否能停止合并。。。

        c.最后结构体整体停止对齐。

        4)如果位域字段之间穿插着非位域字段,则不停止压缩,按照不包含位域的结构体停止对齐,详细规则可以参考我以前写的文章:http://blog.csdn.net/todd911/article/details/6528428

        例:

        struct test4

        {

        char a:1;

        char b:1;

        short c;

        char d:1;

        };

        占用6个字节。

    文章结束给大家分享下程序员的一些笑话语录: 人在天涯钻,哪儿能不挨砖?日啖板砖三百颗,不辞长做天涯人~

  • 相关阅读:
    Linked List Cycle leetcode java (链表检测环)
    Remove Duplicates from Sorted List II leetcode java
    Remove Duplicates from Sorted List leetcode java
    Merge Two Sorted Lists leetcode java
    Swap Nodes in Pairs leetcode java
    Median of Two Sorted Array leetcode java
    阿里云最便宜的四种域名注册
    nohup和&后台运行,进程查看及终止
    ipv6转ipv4 NAT64与DNS64基本原理概述
    ros使用pppoe拨号获取ipv6,并且下发IPV6的dns到客户机win7
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3074077.html
Copyright © 2011-2022 走看看