【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 声明短整 ...
随机推荐
- 云网络智慧课堂-Qt程序代码开发规范
序言: 编程规范可以提升代码可读性,提高可维护性. 目录: 一.命名规范 二.内存管理规范 三.函数方法规范 四.控制语句规范 五.注释规范 六.排版规范 七.版本管理规范 八.界面编程 词义解释:强 ...
- 概率图模型 · 概率论基础 | 讲的非常好的 KL 散度博客
知乎博客链接:https://zhuanlan.zhihu.com/p/425693597 感觉讲的非常好,谢谢善良的博主
- Canal使用和安装总结
转载请注明出处: 1.定义 Canal 组件是一个基于 MySQL 数据库增量日志解析,提供增量数据订阅和消费,支持将增量数据投递到下游消费者(如 Kafka.RocketMQ 等)或者存储(如 El ...
- JVM 内存模型及特点总结
本文为博主原创,未经允许不得转载: JVM 内存区域主要分为线程私有区域[程序计数器.虚拟机栈.本地方法区].线程共享区域[JAVA 堆.方法区].直接内存. 线程私有数据区域生命周期与线程相同, 依 ...
- Android之AMS原理分析
在学习android框架原理过程中,ams的原理非常重要,无论是在面试中还是在自己开发类库过程中都会接触到. 1 简述 ActivityManagerService是Android最核心的服务,负责管 ...
- Prime Time - 介绍
Prime Time是对timing进行分析 Prime Time使用的是STA方法进行分析 工具会有更新,但是核心内容是不变的 Prime Time(intro to STA) 没有PT工具的时候, ...
- 【TouchGFX】Widgets and Containers
Widgets and Containers 是 TouchGFX 应用最基础的东西,他们贯穿于 UI 的整个开发,属于 TouchGFX 的预制组件,同时也支持自定义实现 Widgets Widge ...
- Laravel - 模板中的url
<!-- 1, url --> <a href="{{url('/')}}">跳转到主页</a> <!-- 2,action 方法 ...
- [转帖]十九、Linux性能优化实战学习笔记- 为什么系统的Swap变高了?
目录 一.什么是文件页?什么是脏页?什么是匿名页? 二.linux swap原理 换出 换入 三.内存回收的时机 1.直接内存回收 2.kswapd0内核线程 四.NUMA 与 Swap关系 五.sw ...
- [转帖]Oracle安装 - shmmax和shmall设置
https://www.cnblogs.com/ddzj01/p/16108010.html 一.概述 在Linux上安装oracle,需要对内核参数进行调整,其中有shmmax和shmall这两个参 ...
