C/C++中内存对齐问题的一些理解(转)
内存对齐指令
- 一般来说,内存对齐过程对coding者来说是透明的,是由编译器控制完成的
- 如对内存对齐有明确要求,可用#pragma pack(n)指定,以n和结构体中最长数据成员长度中较小者为有效值
- 如未明确指定时,以结构体中最长的数据成员长度作为内存对齐的有效值
以下如没有特殊说明,均视为情况3(未明确指定)计算
内存对齐的三条规则
- 数据成员对齐规则,结构体(struct)(或联合(union))的数据成员,第一个数据成员存放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员(只要该成员有子成员,比如数组、结构体等)大小的整数倍开始(如:int 在 64bit 目标平台下占用 4Byte,则要从4的整数倍地址开始存储)
- 结构体作为成员,如果一个结构体里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储
- 结构体的总大小,即sizeof的结果,必须是其内部最大成员长度(即前面内存对齐指令中提到的有效值)的整数倍,不足的要补齐
另外还有两个需要注意的点:
- 数组在内存中存储时是分开存储的,char类型的数组每个元素是 1Byte,内存对齐时按照单个元素进行对齐
- union(联合体)类型中的数据共用内存,联合的所有成员共用一段内存空间,存储地址的起始位置都相同,一般来说最大成员的内存宽度作为union的内存大小,主要的原因是为了节省内存空间,默认的访问权限是公有的,但是它同样要遵守内存对齐的原则,特别是第3条规则
- C++中空结构体占用 1Byte
- C++中空类同样是占用 1Byte的内存空间(剑指offer 2.2.1节中中提到,当声明该类型的实例的时候,必须在内存中占有一定的空间,否则无法使用这些实例,占用多少内存由编译器决定)
下面开始举栗子说明
栗子1
struct Test1 {
int a;
double b;
char c;
};
解释:
- int a; 占用 4Byte(存储位置0-3),规则1
- double b; 占用 8Byte(存储位置是从该类型长度(也就是 8Byte)或整数倍开始存储8-15),规则1
- char c; 占用 1Byte(存储位置16),规则1
- 这时一共用了17 Byte,但是sizeof所得的大小为24,这就用到了第3条规则,最后sizeof的大小还必须是内部最大成员长度的整数倍,不足的要补齐,这个结构体中最大成员是double b; 8 Byte,最后sizeof的大小为24,规则3
栗子2
struct Test2 {
int a;
double b;
char c[6];
};
解释:
- int a; 占用 4Byte(存储位置0-3),规则1
- double b; 占用 8Byte(存储位置是从该类型长度(也就是 8Byte)或整数倍开始存储8-15),规则1
- 数组在内存中存储时是分开存储的,char类型的数组每个元素是 1Byte,按单个元素进行内存对齐,故sizeof大小还是24,注意1 & 规则3
栗子3
struct Test {
int a;
double b;
char c;
};
struct Test3 {
int a;
Test d;
double b;
char c;
};
解释:
- int a; 占用 4Byte(存储位置0-3),规则1
- Test中最大的元素是double b; 占用 8Byte,Test中的成员是按照 8Byte 的整数倍的地址开始存储的,Test中int a; 占用 4Byte(存储位置8-11),double b; 占用 8Byte(存储位置16-23),char c; 占用 1Byte(存储位置24),规则2
- double b; 占用 8Byte(存储位置32-39),规则1
- char c; 占用1 Byte(存储位置40),不是最大元素大小8的整数倍,按照规则3补齐,sizeof为48,规则1 & 规则2 & 规则3
栗子4
struct Test {
int a;
double b;
char c;
};
struct Test3 {
int a;
Test d;
char c;
};
解释:
- Test3中的最大数据成员大小比成员结构体Test内部最大成员大小要小,这时规则3是按照成员结构体内部的最大成员的整数倍进行补齐的,sizeof的结果是40
//联合体
栗子5
union Test{
char a[20];
int b;
float c;
};
解释:
1. sizeof的大小是20,即a[20]的大小,同样20是b和c的倍数,规则3
栗子6
union Test{
char a[20];
int b;
float c;
double d;
};
解释:
- sizeof的大小是24,即满足容下a[20],同样24是b、c和d的倍数,规则3
字节对齐的原因:
- 平台原因(移植原因),不是所有的硬件平台都能任意访问地址上的任意数据的,某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常
- 性能原因,经过内存对齐后,CPU的访问效率会得到很大的提高(CPU把内存当成是一块一块的,块的大小可以是2,4,8,16Byte 大小,因此CPU在读取内存时是一块一块进行读取的,当读取块的大小是 4Byte 时,一个数据所占的字节偏移(offset)为3|4|5|6,那么CPU访问数据时便需要访问两次,才能得到完整的数据,经过内存对齐后,便可以通过一次访问CPU获取完整的数据)
彩蛋
struct Test{
int a[3]; //16
double b; //8
char c;//8
};
C/C++中内存对齐问题的一些理解(转)的更多相关文章
- C语言中内存对齐规则讨论(struct)
C语言中内存对齐规则讨论(struct) 对齐: 现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地 ...
- C语言中内存对齐
今天一考研同学问我一个问题,一个结构体有一个int类型成员和一个char类型成员,问我这个结构体类型占多少个字节,我直接编个程序给他看结果.这个结构体占八个字节,咦,当时我蛮纳闷的,一个int类型四个 ...
- C语言中内存对齐方式
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
- VC++中内存对齐
我们经常看到求 sizeof(A) 的值的问题,其中A是一个结构体,类,或者联合体. 为了优化CPU访问和优化内存,减少内存碎片,编译器对内存对齐制定了一些规则.但是,不同的编译器可能有不同的实现,本 ...
- c语言中内存对齐问题
在最近的项目中,我们涉及到了“内存对齐”技术.对于大部分程序员来说,“内存对齐”对他们来说都应该是“透明的”.“内存对齐”应该是编译器的“管辖范围”.编译器为程序中的每个“数据单元”安排在适当的位置上 ...
- 什么是内存对齐,go中内存对齐分析
内存对齐 什么是内存对齐 为什么需要内存对齐 减少次数 保障原子性 对齐系数 对齐规则 总结 参考 内存对齐 什么是内存对齐 弄明白什么是内存对齐的时候,先来看一个demo type s struct ...
- C语言中内存对齐与结构体
结构体 结构体是一种新的数据类型,对C语言的数据类型进行了极大的扩充. struct STU{ int age; char name[15]; }; struct STU a; //结构体实例 str ...
- c/c++中内存对齐完全理解
一,什么是内存对齐?内存对齐用来做什么? 所谓内存对齐,是为了让内存存取更有效率而采用的一种编译阶段优化内存存取的手段. 比如对于int x;(这里假设sizeof(int)==4),因为cpu对内存 ...
- C++继承体系中的内存对齐
本篇随笔讨论一个比较冷门的知识,继承结构中内存对齐的问题,如今内存越来越大也越来越便宜,大部分人都已经不再关注内存对齐的问题了.但是作为一个有追求的技术人员,实现功能永远都是最基本的要求,把代码优化到 ...
随机推荐
- 【KM算法】UVA 11383 Golden Tiger Claw
题目大意 给你一个\(n×n\)的矩阵G,每个位置有一个权,求两个一维数组\(row\)和\(col\),使\(row[i] + col[j]\ge G[i][j]\),并且\(∑row+∑col\) ...
- RabbitMQ消息队列总结
AMQP[高级消息队列协议] 是一个异步消息传递所使用的应用层协议规范(是线路层协议)AMQP 客户端能够无视消息的来源任意发送和接受信息 队列的使用场景: 1.与业务的主要逻辑无关,但又需要执行,就 ...
- Linux命令之date +%F
date命令显示当前日期 date +%F显示当前日期 [10:02:52 root@C8[ 2020-06-16DIR]#touch `hostname`_`date +%F`.log [10:03 ...
- 虚拟环境与local_settings
虚拟环境(virtualenv) 对于同时管理多个不同的项目时,使用虚拟环境是必须的. 虚拟环境就是用来为一个项目新建一个全新的纯净的python运行环境,该环境与系统的python环境相互隔离,且虚 ...
- 关于设置Vscode缩进,保存代码任然缩进无效解决方式
在Vscode按F1,运行命令,输入Formatter config 把内容更改为以下代码 { "onSave": true, "javascript": { ...
- error: Please reinstall the libzip distribution
安装中遇到的问题 在运行 ./configure 时,提示: Please reinstall the libzip distribution 是因为 libzip 版本过低,编译升级 先卸载了原先的 ...
- MAP;MLE
判别学习算法:直接对问题进行求解,比如二分类问题,都是在空间中寻找一条直线从而把类别的样例分开,对于新的样例只要判断在直线的那一侧就可. ==>这种直接求解的方法称为判别学习方法 生成学习算法: ...
- java数据结构-04单循环链表
单循环链表与单链表的不同是,单循环链表尾结点的next指向第一个结点(或头结点) 代码: 无头结点: public class SingleCircleLinkedList<E> ext ...
- 获取url中查询字符串参数
// 获取url中查询字符串参数 例如http://www.test.com?a=1&b=2 function RequestParamete() { var url = window.loc ...
- python机器学习实现人脸图片自动补全
人脸自动补全 关注公众号"轻松学编程"了解更多. 1.导包 import matplotlib.pyplot as plt import numpy as np import pa ...