学习总结

内存对齐三原则:

  1. 数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节,则要从4的整数倍地址开始存储。
  2. 结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)
  3. 结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的整数倍.不足的要补齐。

首先了解内存对齐是什么?

简单来讲内存对齐是一种提高内存访问速度的策略,cpu在访问未对其的内存需要经过俩次内存访问,而经过内存对齐一次就可以了。

首先第一点要知道的是,内存对齐默认为4字节对齐,当有比4字节更大的类型时,按更大的类型的字节进行对齐。

例如:

#include <iostream>using namespace std;
struct Examples
{char a;short b;
};int main()
{Examples ls;cout << sizeof(Examples) << endl;printf("%p\n", &(ls.a));cout << &(ls.b) << endl;//char  a 的内存起始地址为 012FFE6C//short b 的内存起始地址为 012FFE6Ereturn 0;
}

#include <iostream>using namespace std;
struct Examples
{char a;short b;long long c;
};int main()
{Examples ls;cout << sizeof(Examples) << endl;printf("%p\n", &(ls.a));cout << &(ls.b) << endl;cout << &(ls.c) << endl;return 0;
}/*
此时 Examples结构体的大小为24字节
ls.a的起始地址是 00DAFD90
ls.b的起始地址是 00DAFD92
ls.c的起始地址是 00DAFD98
*/

由上可证明 内存对齐的默认对齐大小为 4字节,当有比4字节更大的类型时,按更大的类型的字节进行对齐。

但是同样也要注意一点,内存对齐的标准时对于不同类型的数据成员之间的对齐。

然后我们由上例进行进一步的改造来加深一下我们对内存对齐的理解

#include <iostream>using namespace std;
struct Examples
{char a;       //4int  b;       //4long long c;  //8short d;      //2char f;       //6
};int main()
{Examples ls;cout << sizeof(Examples) << endl;printf("%p\n", &(ls.a));cout << &(ls.b) << endl;cout << &(ls.c) << endl;cout << &(ls.d) << endl;printf("%p\n", &(ls.f));return 0;
}/*
此时 Examples结构体的大小为24字节
ls.a的起始地址是 010FF8B4
ls.b的起始地址是 010FF8B8
ls.c的起始地址是 010FF8BC
ls.d的起始地址是 010FF8C4
ls.f的起始地址是 010FF8C6
*/


首先我们来看一下这个结构体各个成员的内存大小
a = 4字节
b = 4字节
c = 8字节
d = 2字节
f = 6字节
结构体大小为 4 + 4 + 8 + 2 + 6 =24

然后我们来理解一下为何各个数据成员的内存大小为这些呢?

1、a为何为4字节
a 为 char 类型 1 字节的数据成员,而 b 为int 类型4 字节的数据成员。所以 a要对b进行内存对齐,所以此时的 a为4个字节。
2、b为何也为4字节
c 的类型为 long long ,8字节的数据成员。b为4字节,所以按照内存对齐规则,此时的 b应该为8字节才对,为何是4字节呢?因为 a的内存大小此时也为4字节,4 + 4 = 8字节 同样符合内存对齐规则,所以此时的b也为4字节。同理 d 与 f 也可套用此原理。d 的内存大小为2字节,而 f 的内存大小为6字节,2 + 6 = 8,同样符合内存对齐规则。原因就是内存地址对齐时,如果数据成员之间的大小相加不超过需要对齐的内存大小时,多个数据成员会整合到同一个内存空间中。

我们依旧可以使用一个例子来证明:

#include <iostream>using namespace std;
struct Examples
{char a;short g;int  b;long long c;short d;char f;
};int main()
{Examples ls;cout << sizeof(Examples) << endl;printf("%p\n", &(ls.a));cout << &(ls.g) << endl;cout << &(ls.b) << endl;cout << &(ls.c) << endl;cout << &(ls.d) << endl;printf("%p\n", &(ls.f));return 0;
}
/*
此时 Examples结构体的大小依旧为24字节
ls.a的起始地址是 00D6FEC4
ls.g的起始地址是 00D6FEC6
ls.b的起始地址是 00D6FEC8
ls.c的起始地址是 00D6FECC
ls.d的起始地址是 00D6FED4
ls.f的起始地址是 00D6FED6
*/

简单理解结构体的内存对齐相关推荐

  1. c 定义结构体时提示应输入声明_C++|了解结构体的内存对齐(成员声明的顺序影响占用空间大小)...

    我们使用的电子计算机绝大部分都是冯·诺依曼结构的机器,遵循"存储程序"的概念.数据处理以存储为前提,在编程中数据如何"存得进去,取得出来",并且符合空间.时间效 ...

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

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

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

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

  4. 结构体的内存对齐规则

    1.结构体的内存对齐规则 1.第一个成员在与结构体变量偏移量为0的地址处. 2.其他成员变量都放在对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处. 对齐数=编译器默认的一个对齐数与该成员大小 ...

  5. C语言--结构体与内存对齐准则简单理解

    平时基本不涉及这个问题,被问起才发现没那么简单... 一,结构体:内存中所有类型字节之和 #include<stdio.h> struct icd {int a;char b;double ...

  6. 字节对齐《c和指针》笔记--包含位域结构体的内存对齐(32bit,GCC)

    最近使用开发的过程中出现了一个小问题,顺便记录一下原因和方法--字节对齐 C99划定int.unsigned   int和bool可以作为位域类型.但编译器几乎都对此作了扩展,答应其它类型类型的存在. ...

  7. 3.c语言结构体成员内存对齐详解

    一.关键一点 最关键的一点:结构体在内存中是一个矩形,而不是一个不规则形状 二.编程实战 1 #include <stdlib.h> 2 #include <stdio.h> ...

  8. [转]C++结构体|类 内存对齐详解

    内存地址对齐,是一种在计算机内存中排列数据(表现为变量的地址).访问数据(表现为CPU读取数据)的一种方式,包含了两种相互独立又相互关联的部分:基本数据对齐和结构体数据对齐 . 为什么需要内存对齐?对 ...

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

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

最新文章

  1. pythonflask configlist.py_flask源码阅读系列一config模块
  2. 9102年webpack4搭建vue项目
  3. Ubuntu10.04中IBus随系统启动的方法
  4. ASP.Net请求小周期
  5. php连接mysql并查询表数据,php连接mysql并查询数据怎么实现
  6. 【转】Ubuntu 16.04 安装 CUDA10.1 (解决循环登陆的问题)
  7. WinDBG 技巧:如何生成Dump 文件(.dump 命令)
  8. mysql 排他,mysql 共享锁 排他锁 防插入锁
  9. 动态引入js只能生效一次_动态插入的script脚本执行时间
  10. 计算机英语初级考试时间,2020年考研考试时间安排及考试科目_考研网
  11. Java连接程序数据源
  12. y700支持m2硬盘_两块硬盘一起读写?奥睿科M.2 NVMe双盘位固态硬盘盒使用
  13. 【PHP编程】制作表单生成器——注册登录信息
  14. CentOS7—Firefox—截图工具—fireshot插件
  15. 【Unity Shaders】Using Textures for Effects——通过修改UV坐标来滚动textures
  16. 服务器上的文件都变成只读了,[求助]Excel 文档都变成只读了,请问怎么恢复?/excle变成只读文件怎么办...
  17. 黑龙江农垦科技职业学院喜迎寒假多校联赛2(快乐ak场)
  18. NOIP2004P4 火星人 题解
  19. iFixit高清完整拆解:iPhone 7 Plus
  20. CF337A Maze 解题报告

热门文章

  1. 什么是WLIDSVC.EXE和WLIDSVCM.EXE,它们为什么运行?
  2. Windows CreateFont
  3. Linux下Stunnel的安装和使用
  4. 升达经贸管理学院计算机专业英语四级,关于2018年12月全国大学英语四六级考试郑州升达经贸管理学院考点工作安排的通知...
  5. mac系统中Safari浏览器网页如何保存至备忘录Notes?
  6. listview下拉刷新上拉加载扩展(二)-仿美团外卖
  7. 【Python案例】短视频转动漫效果
  8. “宝塔”同IP不同端口分别对应不同网站教程
  9. 扬帆志远—tiktok跨境电商运营流程
  10. 20200728-直接提取压缩包里的文件