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个字节。

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

  • 相关阅读:
    北京 到 娄底 灌湄
    AVR--IO设置编程
    AVR--I/O端口寄存器
    AVR--IO结构分析
    虚拟机VM下 UBUNTU 下安装Mantis
    Windows环境下Mantis搭建概述
    SW4STM32 : Error message from debugger back end: Error erasing flash with vFlashErase packet Error erasing flash with vFlashErase packet
    三极管驱动继电器详解
    STM32 Bootloader 跳转到App
    (转载) STM32IAP升级---IAP升级功能编写初期的一些困惑与疑问---完成功能后的总结
  • 原文地址:https://www.cnblogs.com/xinyuyuanm/p/3074077.html
Copyright © 2011-2022 走看看