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

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

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

字节对齐《c和指针》笔记--包含位域结构体的内存对齐(32bit,GCC)相关推荐

  1. C语言:指针的偏移步长、结构体成员的偏移量、嵌套结构体成员的偏移量、结构体的内存对齐

    文章目录 1 不同类型指针的偏移步长 2 结构体成员的偏移量 3 嵌套结构体成员的偏移量 4 结构体的内存对齐 4.1 内存对齐的原因与优点 4.2 结构体内存对齐的规则 4.3 结构体嵌套结构体时的 ...

  2. 自定义类型详解:结构体(内存对齐、位段) + 枚举 + 联合

    目录 一.结构体 1.特殊的声明 2.结构体自引用 3.结构体变量的定义和初始化 4.打印结构体 二.==结构体内存对齐== 1.内存对齐 结构体嵌套如何求 为什么存在内存对齐? 2.修改默认对齐数 ...

  3. c 定义结构体时提示应输入声明_C++|了解结构体的内存对齐(成员声明的顺序影响占用空间大小)...

    我们使用的电子计算机绝大部分都是冯·诺依曼结构的机器,遵循"存储程序"的概念.数据处理以存储为前提,在编程中数据如何"存得进去,取得出来",并且符合空间.时间效 ...

  4. 结构体的内存对齐规则

    1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处. 2.其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处. 对齐数=编译器默认的一个对齐数与该成员大小 ...

  5. 基于STM32使用嵌套结构体摸索内存对齐

    导读 一.结构体的声明以及初始化 二.结构体成员的内存对齐规则 三.联合体以及嵌套结构体的用法 位段 小端模式 三.位段数据跨字节单位导致的内存对齐现象 用来描述对象特征的各类信息,通常会被整合成记录 ...

  6. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

  7. 关于结构体的内存对齐,以及如何计算

    在C语言中,我们的类型有两种一种是内置类型,另一种是自定义类型,今天我们来看一下自定义类型占用字节数的计算 首先我们知道自定义类型中包含一些内置类型,其中内置类型的大小我们是知道的,那么自定义类型的大 ...

  8. 结构体知识点内存对齐位段、枚举、联合

    ***结构体类型创建*** ***结构体初始化*** struct Stu{ char name[20]; int age; char sex[5];char id[20]; } Stu1; 在这里S ...

  9. 3.c语言结构体成员内存对齐详解

    一.关键一点 最关键的一点:结构体在内存中是一个矩形,而不是一个不规则形状 二.编程实战 1 #include <stdlib.h> 2 #include <stdio.h> ...

最新文章

  1. RabbitMQ消息队列(二):”Hello, World“
  2. 蓝桥杯最短路(java过)spfa单源最短路算法
  3. wxWidgets:在对话框之间共享信息
  4. 81. 搜索旋转排序数组 II
  5. LDAP命令介绍---dsreplication
  6. 【BZOJ3289】Mato的文件管理,莫队+树状数组
  7. 【声学基础】概述——吸收
  8. 使用ef core自动生成mysql表和数据编码的问题
  9. linux activemq 日志,log4j通过ActiveMQ远程记录日志设计配置
  10. 自己应该如何不断学习呢?
  11. 安装anaconda,jupyter基本操作说明快捷键使用
  12. c程序-RGB转十六进制
  13. 计算机延时关机小程序,电脑自动关机小程序
  14. java实现HTTPS单向认证TLS指定加密套件(文章很详细,好文章!)
  15. github帐户和仓库的创建
  16. 旗帜工作室2021年会总结
  17. 记Aspose.Word的使用中出现的问题
  18. 一年站长经历后的感悟
  19. 郑莉老师c++第五版+b站视频 学习笔记
  20. USTC高级软件工程课程学习总结和心得

热门文章

  1. java语言程序设计答案_《java语言程序设计》练习题及答案
  2. 个推微服务网关架构实践
  3. 7.1Python异常处理
  4. 提问的智慧 如何得到好的帮助(转)
  5. Android零基础入门第7节:搞定Android模拟器,开启甜蜜之旅
  6. 代码的世界中,一个逻辑套着另外一个逻辑,如何让每一种逻辑在代码中都有迹可循?...
  7. 先序、中序确定二叉树
  8. flink-jdbc-driver和flink-sql-gateway的作用
  9. WARN RestSubmissionClient: Unable to connect to server spark://master:
  10. hexo的yelee主题使用katex引擎(markdown渲染加速)