结构体内存对齐

大家好,我是西城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类型),但其实,输出结果并不是这样的:

其实结构体大小的计算远没有成员直接相加这么简单,接下来我们进入正题:结构体内存对齐

结构体内存对齐

首先得掌握结构体的对齐规则:

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

当然,光看概念规则,伙伴们估计是一头雾水了,接下来,博主给大家举几个例子,大家就明白了。

例子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语言深度解剖】一篇搞懂结构体内存对齐【结构体的大小你会算了吗】的更多相关文章

  1. C语言-结构体内存对齐

    C语言结构体对齐也是老生常谈的话题了.基本上是面试题的必考题.内容虽然很基础,但一不小心就会弄错.写出一个struct,然后sizeof,你会不会经常对结果感到奇怪?sizeof的结果往往都比你声明的 ...

  2. go语言结构体内存对齐

    cpu要想从内存读取数据,需要通过地址总线,把地址传输给内存,内存准备好数据,输出到数据总线,交给cpu,如果地址总线只有8根,那这个地址就只有8位可以表示[0,255]256个地址,因为表示不了更多 ...

  3. C语言中结构体内存对齐

    先写一个小程序: #include<stdio.h> struct student  {    int a;   char k;   short m; }; int main() { st ...

  4. C语言之结构体内存的对齐

    C语言之结构体内存的对齐 大纲: 零.引例 一.结构体内存对齐规则 二.怎样计算结构体的大小 三.设计结构体时要注意的方面   四.为什么存在内存对齐 五.修改默认对齐数 在前面的章节中,我们谈到了C ...

  5. C语言深度解剖读书笔记

    开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有一段时间了,一直没有时间来写这篇博客.正巧还刚刚看完了国嵌唐老师的C语言视频,觉得两者是异曲同工,所以就把两者一起记录下 ...

  6. 【转】 C语言深度解剖读书笔记(1.关键字的秘密)

    本文出处:http://blog.csdn.net/mbh_1991/article/details/10149805 开始本节学习笔记之前,先说几句题外话.其实对于C语言深度解剖这本书来说,看完了有 ...

  7. C语言深度解剖读书笔记(6.函数的核心)

    对于本节的函数内容其实就没什么难点了,但是对于函数这节又涉及到了顺序点的问题,我觉得可以还是忽略吧. 本节知识点: 1.函数中的顺序点:f(k,k++);  这样的问题大多跟编译器有关,不要去刻意追求 ...

  8. C++ 一篇搞懂多态的实现原理

    虚函数和多态 01 虚函数 在类的定义中,前面有 virtual 关键字的成员函数称为虚函数: virtual 关键字只用在类定义里的函数声明中,写函数体时不用. class Base { virtu ...

  9. C语言中结构体内存存储方式

    C语言中结构体内存存储方式 结构体的默认存储方式采用以最大字节元素字节数对其方式进行对齐,例如一个结构体中定义有char.int类型元素,则结构体存储空间按照int类型占用字节,如果还有double类 ...

  10. 《C语言深度解剖》学习笔记之关键字

    第一章 关键字 C语言共有32个关键字. 关键字   auto 声明自动变量 int 声明整型变量 long 声明长整型变量 char 声明字符型变量 float 声明浮点型变量 short 声明短整 ...

随机推荐

  1. Educational Codeforces Round 109 (Rated for Div. 2) 个人补题记录(A~D,AB思维,C模拟构造,D题DP)

    补题链接:Here 1525A. Potion-making (思维 [题意描述] 作为一个魔法师,现在我想配置一杯药物浓度为 \(k\%\) 的药水, 每次操作能进行添加: 一升水 一升药物精华 作 ...

  2. Codeforces Round #715 (Div. 2) (A~D 补题记录)

    补题链接:Here 经典手速场 1509A. Average Height 题意:要找出最大不平衡对序列 先输出奇数,然后输出偶数 void solve() { int n; cin >> ...

  3. Tomcat 9.0.26 高并发场景下DeadLock问题排查与修复

    本文首发于 vivo互联网技术 微信公众号 链接:https://mp.weixin.qq.com/s/-OcCDI4L5GR8vVXSYhXJ7w作者:黄卫兵.陈锦霞 一.Tomcat容器 9.0. ...

  4. 2021 VDC :vivo 互联网服务亿级用户的技术架构演进之路

    关注公众号[vivo互联网技术]--回复[2021VDC]获取大会PPT. 2021年12月16日,vivo 开发者大会圆满落幕.在互联网技术专场中,来自vivo 互联网技术的6位研发专家,从基础架构 ...

  5. S3C2440移植uboot之支持DM9000

      上一节S3C2440移植uboot之支持NANDFLASH操作移植了uboot 支持了NANDFLASH的操作,这一节修改uboot支持DM9000. 目录 通过Makefile把dm9000x编 ...

  6. java基础(3)--pulic class与class的区别

    1.一个类前面的public是可有可无的2.如果一个类使用 public 修饰,则文件名必须与类名一致3.如果一个类前面没有使用public修饰,则文件名可以与类名不一致.当编译成功后会生成对应类名的 ...

  7. ApplicationContextAware 的理解和应用

    当我们在项目中获取某一个spring bean时,可以定义一个类,实现ApplicationContextAware  该接口,该接口可以加载获取到所有的 spring bean. package c ...

  8. 基于html+javascript开发的base64解码工具

    base64在线解码工具可以帮助你将Base64编码的字符串解码为原始的文本或数据. 预览入口 以下是一个简单的base64在线解码工具的示例: html <!DOCTYPE html> ...

  9. DC-设计和工艺数据-02

    在 compile之前保存ddc设计文件 check design - 检查文件的连接性和物理性 check design之后可以将未映射的网表写出,如果是几十万级的RTL,如果不写出,设置约束出现问 ...

  10. [转帖]设置kafka 数据保留时间

    https://www.cnblogs.com/gao88/p/12539112.html kafka 单独设置某个topic的数据过期时间kafka 默认存放7天的临时数据,如果遇到磁盘空间小,存放 ...