【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 声明短整 ...
随机推荐
- Live Server插件打开浏览器时:该网页无法正常运作,127.0.0.1未发送任何数据的问题解决
一.问题复现 今天使用Vs Code写HTML代码时,使用Live Server打开预览时,发现浏览器显示"该网页无法正常运作,127.0.0.1未发送任何数据"的问题. 二.解决 ...
- es6-10
- C# 开发桌面应用简单介绍
一. C#使用场景介绍 C#是微软公司发布的一种由C和C++衍生出来的面向对象的编程语言.运行于.NET Framework和.NET Core(完全开源,跨平台)之上的高级程序设计语言. 二. 开发 ...
- 线段树的区间更新 hdu 1698
***第一次写的果断超时,所以百度了一下,知道我写的每一次都要递归最底层,这样会花费很多时间,第二次写得线段树的区间更新,因为一个条件写错了,真是让我坑到死, 这样区间相同的不必更新,省了很多时间.. ...
- MINGW64 禁用 Bash 路径参数转换
MINGW64 可以让 Windows 无缝使用 Linux 命令,但是路径参数会被转换为 Windows 风格.例如: $ ./adb shell ls /system ls: C:/Program ...
- java基础数据类型-int类型-浮点型-数据类型的转换--day02
目录 1. 变量的命名 2. 常量 3. 变量 4. 进制 4.1 进制转换 4.2 整型数据类型 5 浮点型 6. 字符串 7. 整形与字符型之间的转换 8 最常见的一个乱码问题 9. 布尔类型 1 ...
- Linux系统CPU异常占用(minerd 、tplink等挖矿进程)
转载请注明出处: 云服务器ECS(Linux) CPU使用率超过70%,严重时可达到100%,服务器响应越来越慢. 服务器中存在恶意minerd.tplink进程 该进程是服务器被入侵后,被恶意安装 ...
- 分享Go书籍-《Go Web编程》
大家好,我是沙漠尽头的狼. 最近几天在看一本Go的书籍,看了100来页,感觉不错,分享给大家. 书籍基本信息 书籍信息: 书名:Go Web编程 作 者:(新加坡)郑兆雄(Sau Sheong C ...
- [转帖]Linux nice和renice命令:改变进程优先级
https://c.biancheng.net/view/1074.html 当 Linux 内核尝试决定哪些运行中的进程可以访问 CPU 时,其中一个需要考虑的因素就是进程优先级的值(也称为 nic ...
- [转帖]使用 BR 命令行备份恢复
TiDB试用 来源:TiDB 浏览 404 扫码 分享 2021-04-20 20:49:42 使用 BR 命令行进行备份恢复 BR 命令行描述 命令和子命令 常用选项 使用 BR 命令行备份集群数 ...
