学习总结

内存对齐三原则:

  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. golang TCP Socket编程
  2. Disruptor之概览
  3. 2020年度“CCF-百度松果基金”评审结果公示
  4. VTK:几何对象之PlaneSource
  5. mysql5.7 修改密码
  6. 详解MySQL中DROP,TRUNCATE 和DELETE的区别
  7. centos 配置mysql环境变量_Centos7.1部署mysql-5.6.34(笔记)
  8. 基于JAVA+SpringMVC+Mybatis+MYSQL的在线学习管理系统源码
  9. MyBatis学习总结(24)——Mybatis常见问题汇总
  10. 下拉框数据绑定两种方式
  11. 谷歌详述 Zoom 客户端和MMR 服务器中的两个0day
  12. AS3 JPEG Encoder应用:从Flash中保存图片
  13. 读嵌入式linux驱动程序设计从入门到精通 3
  14. 2018年程序员书单
  15. 微信撤回软件安卓版_微信强制撤回app
  16. 基于php的外卖订餐系统开题报告_网上订餐系统开题报告
  17. mysql创建视图注意事项_mysql视图创建注意事项(转)
  18. Lighttools中模拟白光LED
  19. Spire.PDF 教程:在C#中显示或隐藏PDF图层
  20. js实现html图片翻页效果,原生JS实现图片翻书效果

热门文章

  1. 2023年高企统计年报填写程序
  2. [附源码]PHP计算机毕业设计会议室预约系统(程序+LW)
  3. Weave常见问题集合
  4. 现代信号处理笔记 1 概率论基础知识(Review of Probability)
  5. 升达经贸管理学院计算机专业英语四级,关于2018年12月全国大学英语四六级考试郑州升达经贸管理学院考点工作安排的通知...
  6. java api是什么_JAVA_API概述
  7. lsblk命令与blkid命令
  8. mysql密码输入正确但是登陆不进去
  9. iptables简单使用
  10. REST(Representational State Transfer)简介