【C语言深度解剖】一篇搞懂结构体内存对齐【结构体的大小你会算了吗】
结构体内存对齐


大家好,我是西城s
前言
作者: #西城s
这是我的主页:#西城s
在食用这篇博客之前,博主在这里介绍一下其它高质量的编程学习栏目:
数据结构专栏:数据结构 这里包含了博主很多的数据结构学习上的总结,每一篇都是超级用心编写的,有兴趣的伙伴们都支持一下吧!
算法专栏:算法 这里可以说是博主的刷题历程,里面总结了一些经典的力扣上的题目,和算法实现的总结,对考试和竞赛都是很有帮助的!
力扣刷题专栏:Leetcode想要冲击ACM、蓝桥杯或者大学生程序设计竞赛的伙伴,这里面都是博主的刷题记录,希望对你们有帮助!
C的深度解剖专栏:C语言的深度解剖想要深度学习C语言里面所蕴含的各种智慧,各种功能的底层实现的初学者们,相信这个专栏对你们会有帮助的!
引入
大家看这个代码,伙伴们觉得这个代码执行的结果是什么?
struct S1 {
char c1;
int i;
char c2;
};
//顺序换一下
struct S2 {
char c1;
char c2;
int i;
};
int main() {
struct S1 s1;
struct S2 s2;
printf("%d\n", sizeof(s1));
printf("%d\n", sizeof(s2));
return 0;
}
#endif
如果还没有了解过结构体内存对齐方面的知识的伙伴们,一定会认为这两个个结构体的大小都是6个字节(两个char类型和一个int类型),但其实,输出结果并不是这样的:

其实结构体大小的计算远没有成员直接相加这么简单,接下来我们进入正题:结构体内存对齐。
结构体内存对齐
首先得掌握结构体的对齐规则:
- 第一个成员在与结构体变量偏移量为0的地址处。
- 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8 - 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整
体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
当然,光看概念规则,伙伴们估计是一头雾水了,接下来,博主给大家举几个例子,大家就明白了。
例子1:
struct S1 {
char c1;
int i;
char c2;
};

例子2:
struct S3 {
double d;
char c;
int i;
};

相信看到这里,大家已经会自己计算一个结构体所占内存的大小了。
offsetof宏的使用
使用offsetof宏,我们就可以知道我们刚才的推导过程是否是正确的。
作用:计算结构体中某变量相对于首地址的偏移
所要包含的头文件:#include<stddef.h>
图片来自www.cplusplus.com

使用举例:
#include<stddef.h>
struct S {
int a;
char c;
double d;
};
int main() {
printf("%d\n", offsetof(struct S, a));//0
printf("%d\n", offsetof(struct S, c));//4
printf("%d\n", offsetof(struct S, d));//8
return 0;
}
当然有关offsetof这个宏的模拟实现,博主已经在另一篇博客中详细介绍了,有需要的伙伴们可以通过传送门食用~
【C语言深度解剖】预定义章节经典面试题讲解(offsetof宏模拟实现)【超详细的解释和注释】
为什么存在结构体内存对齐
平台原因(移植原因)
- 不是所有的硬件平台都可以访问任意地址上的任意数据的,某些硬件平台只能在某些
- 地址处取某些特定类型的数据,否则抛出硬件异常。
性能原因
- 数据结构(尤其是栈)应该尽可能地在自然边界上对齐
- 原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对齐的内存访问只需要一次访问
总体来说:
结构体的内存对齐时拿空间来换取时间的做法
因此我们在设计结构体的时候
我们要满足对齐,又要节省空间,如何做到呢?
—将占空间小的成员尽量放在一起
修改默认对齐数
指令:#pragma pack()
使用举例:(将默认对齐数修改为4)
#pragma pack(4)
struct S {
char c;
double d;
};
#pragma pack()
int main() {
struct S s;
printf("%d\n", sizeof(s));
return 0;
}
尾声
相信看到这里,各位已经对结构体内存对齐这方面的内容有了一定的了解了,如果你感觉这篇文章对你有帮助的话,不要忘了一键三连再离开噢!

【C语言深度解剖】一篇搞懂结构体内存对齐【结构体的大小你会算了吗】的更多相关文章
- C语言-结构体内存对齐
C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...
- go语言结构体内存对齐
cpu要想从内存读取数据,需要通过地址总线,把地址传输给内存,内存准备好数据,输出到数据总线,交给cpu,如果地址总线只有8根,那这个地址就只有8位可以表示[0,255]256个地址,因为表示不了更多 ...
- C语言中结构体内存对齐
先写一个小程序: #include<stdio.h> struct student { int a; char k; short m; }; int main() { st ...
- C语言之结构体内存的对齐
C语言之结构体内存的对齐 大纲: 零.引例 一.结构体内存对齐规则 二.怎样计算结构体的大小 三.设计结构体时要注意的方面 四.为什么存在内存对齐 五.修改默认对齐数 在前面的章节中,我们谈到了C ...
- C语言深度解剖读书笔记
开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有一段时间了,一直没有时间来写这篇博客.正巧还刚刚看完了国嵌唐老师的C语言视频,觉得两者是异曲同工,所以就把两者一起记录下 ...
- 【转】 C语言深度解剖读书笔记(1.关键字的秘密)
本文出处:http://blog.csdn.net/mbh_1991/article/details/10149805 开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有 ...
- C语言深度解剖读书笔记(6.函数的核心)
对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++); 这样的问题大多跟编译器有关,不要去刻意追求 ...
- C++ 一篇搞懂多态的实现原理
虚函数和多态 01 虚函数 在类的定义中,前面有 virtual 关键字的成员函数称为虚函数: virtual 关键字只用在类定义里的函数声明中,写函数体时不用. class Base { virtu ...
- C语言中结构体内存存储方式
C语言中结构体内存存储方式 结构体的默认存储方式采用以最大字节元素字节数对其方式进行对齐,例如一个结构体中定义有char.int类型元素,则结构体存储空间按照int类型占用字节,如果还有double类 ...
- 《C语言深度解剖》学习笔记之关键字
第一章 关键字 C语言共有32个关键字. 关键字 auto 声明自动变量 int 声明整型变量 long 声明长整型变量 char 声明字符型变量 float 声明浮点型变量 short 声明短整 ...
随机推荐
- python生成word文档
python生成word文档,感觉比java生成方便很多 下面看看步骤 1.环境 pip install python-docx 2.准备一张需要插入word中的图片monty-truth.png 3 ...
- the server responded with a status of 413 (Request Entity Too Large) 解决
前端上传文件,本地测试好的,放到服务器上出现了这个错误:the server responded with a status of 413 (Request Entity Too Large) 问题原 ...
- vue判断用户在页面停留时间是否超时
需求 当用户停留超过15分钟后,用户提交订单,提示用户超时并重新加载页面 代码 data () { return { // 超时定时器 overTimer: null, // 是否超时 isOvert ...
- Mathpix:屏幕截图 ➡ latex 公式,一键转换
安利一天能免费使用 10 次且好用的工具 Mathpix.
- zookeeper源码(06)ZooKeeperServer及子类
ZooKeeperServer 实现了单机版zookeeper服务端功能,子类实现了更加丰富的分布式集群功能: ZooKeeperServer |-- QuorumZooKeeperServer |- ...
- 分享这位大神的WPF界面设计系列视频
本文结构: 前言 视频详情 搬运详情 总结 4.1 国内推荐WPF资源 4.2 B站是学习的天堂 4.3 去外面看看 4.4 个人给C/S同学建议 1. 前言 今天介绍油管上一个大佬发的WPF设计系列 ...
- java - 对象装载数据返回
1. 创建 Phone 类 package class_object; public class Phone { String brand; String color; double price; v ...
- JavaScript : 获取文件名后缀
/** 获取文件后缀 * * indexOf 和 lastIndexOf 都是索引文件 indexO ...
- 在线安装gfortran的方法-CentOS8 or 阿里龙蜥
在线安装gfortran的方法-CentOS8 or 阿里龙蜥 背景 在阿里云上面进行了 speccpu2006的测试验证 但是发现总是很多包安装不过去 原因是阿里最小化安装的龙蜥系统. 缺少很多编译 ...
- 【行云流水线】满足你对工作流编排的一切幻想~skr
流水线模型 众所周知,DevOps流水线(DevOps pipeline)的本质是实现自动化工作流程,用于支持软件开发.测试和部署的连续集成.交付和部署(CI/CD)实践.它是DevOps方法论的核心 ...
