结构体内存对齐

先看一下下面的代码,他们的内存相等吗?

#include <stdio.h>
struct S1
{char c1;int i;char c2;
};struct S2
{char c1;char c2;int i;
};int main(){printf("%d\n", sizeof(struct S1));printf("%d\n", sizeof(struct S2));return 0;
}

当我们运行出来的时候,就可以发现他们是不一样大小的,s1是12,s2是8。

那么问题来了,这是为什么呢?

这就是我们要讲的结构体内存对齐

  1. 第一个成员在与结构体变量偏移量为0的地址处。
  2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 VS中默认的值为8
  3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
  4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。

先画个图来表示一下,再解释一下:

先看S1:

c1开辟了一个字节,这时候准备开辟i的内存,int是4个字节,但是vs默认是8个字节,于是4<8,i的对齐数就是4,所以这时候i从第4个地址开始开辟4个字节,c2的对齐数是1,也就紧跟之后开辟1个字节,最后,整个struct最大对齐数是4,所以现在的地址9得向后再开辟3个,达成12(4的整数倍)

先看S2:

c1开辟了一个字节,c2的对齐数是1,这时候准备开辟i的内存,int是4个字节,但是vs默认是8个字节,于是4<8,i的对齐数就是4,所以这时候i从第4个地址开始开辟4个字节,最后,整个struct最大对齐数是4,所以现在的地址8(4的整数倍),就结束了内存分配。

所以最节省的方法:让占用空间小的成员尽量集中在一起。

那么为什么要内存对齐呢?

1. 平台原因(移植原因): 不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特 定类型的数据,否则抛出硬件异常。

2. 性能原因: 数据结构(尤其是栈)应该尽可能地在自然边界上对齐。 原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访 问。

修改默认对齐数?是的,可以。

#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{char c1;int i;char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{char c1;int i;char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
int main()
{//输出的结果是什么?printf("%d\n", sizeof(struct S1));printf("%d\n", sizeof(struct S2));
return 0;
}

运行结果:12和6。

也是s1的默认对齐数是8,s2的默认对齐数是1。

位段

位段的声明和结构是类似的,有两个不同:

1.位段的成员必须是 int、unsigned int 或signed int 。

2.位段的成员名后边有一个冒号和一个数字。

struct A
{int a:2;int b:5;int c:10;int d:30;
};

也就是a=2bit,b=5bit,c=10bit,d=30bit。运行出来占了8个字节,是不是有不解,这不是47bit,一共6个字节吗?

但其实不是这样的,因为是int会先开辟4个字节,一个32个bit位,这时候abc是可以存进去的,但是对于d来说太少了,于是又开辟4个字节,将d全部存进去。所以就是8个字节

1. 位段的成员可以是 int unsigned int signed int 或者是 char (属于整形家族)类型

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。

关于结构体的内存计算相关推荐

  1. 结构体占用内存的计算

    目录 前言 一.结构体 二.计算方法 总结 前言 大家都知道我们的数据类型如 int,char都有他们各自占据的内存大小,int 是4个字节,char 是一个字节,当我们接触到结构体这个东西的时候,或 ...

  2. 更改结构体的内存字节对齐方式--经典

    结构体字节对齐 http://blog.163.com/ecy_fu/blog/static/4445126200910603739941/ http://hi.baidu.com/skyland_l ...

  3. C语言结构体占用内存总结

    C语言结构体占用内存总结 前几天有个小朋友问了我一下,关于C语言结构体占用空间的问题.觉得以后会对小可爱有点帮助,就打算先写一下. struct Test {int a;char b;int c; } ...

  4. 从结构体、内存池初始化到申请释放,详细解读鸿蒙轻内核的动态内存管理

    摘要:本文带领大家一起剖析了鸿蒙轻内核的动态内存模块的源代码,包含动态内存的结构体.动态内存池初始化.动态内存申请.释放等. 本文分享自华为云社区<鸿蒙轻内核M核源码分析系列九 动态内存Dyna ...

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

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

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

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

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

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

  8. 结构体PLUS(计算结构体类型大小及位段)~~

    如何计算结构体类型大小呢? 1. 结构体内存对齐 为什么要内存对齐呢? 2.修改默认对齐数 3.位段 什么是位段 位段的内存分配 位段的跨平台问题 位段的应用 关于结构体类型,之前阿涛写过一篇文章,里 ...

  9. 【C 语言】结构体 ( 结构体中嵌套一级指针 | 分配内存时先 为结构体分配内存 然后再为指针分配内存 | 释放内存时先释放 指针成员内存 然后再释放结构头内存 )

    文章目录 一.结构体中嵌套一级指针 1.声明 结构体类型 2.为 结构体 变量分配内存 ( 分配内存时先 为结构体分配内存 然后再为指针分配内存 ) 3.释放结构体内存 ( 释放内存时先释放 指针成员 ...

最新文章

  1. php js获取file,PHP file_get_contents 读取js脚本的问题
  2. JQuery Highcharts图表控件使用说明
  3. case when mysql_mysql条件语句case when的实例
  4. CentOS 5安装GIT的基本命令
  5. 棋盘游戏(信息学奥赛一本通-T1451)
  6. 物资管理信息系统4 -- 修改密码界面
  7. 数列极限:数列极限的性质
  8. web前端大一实训 HTML+CSS+JavaScript王者荣耀(60页) web课程设计网页规划与设计 HTML期末大作业 HTML网页设计结课作业...
  9. 2022-2027年中国OLED行业市场调研及未来发展趋势预测报告
  10. Python 名称空间以及函数的补充
  11. 【定量分析、量化金融与统计学】R语言方差分析的outliers陷阱
  12. 微信公众号行业排行榜周榜
  13. Notepad ++中的一个著名插件FingerText
  14. 几何光学学习笔记(18)- 5.1光阑在光学系统中的作用
  15. 西门子S7-1200系列PLC定时器指令
  16. 模电——磁珠的前世今生
  17. AUR 打包自己的软件
  18. Flash播放mp4的两个问题:编码问题和需要下载完后才能播放的问题
  19. Windows下telnet 发送邮件
  20. 常用的正则表达式校验

热门文章

  1. 2018年7月16日训练日记
  2. CSS实现侧边栏导航
  3. python跳转下一页_在selenium python中访问下一页上的元素
  4. 达人评测 2022款联想ThinkPad T16和T14区别是什么,哪个好
  5. 实现Choose函数(FreeBasic可变参数数量用法例题)【VFB源码】
  6. 设计模式 - 创建型 - 工厂模式
  7. S电子产品和半导体的X射线检测
  8. 缓存+db 该怎么设计?
  9. ArrayList去重的几种方法
  10. winform 自定义数值(数字)输入框