C/C++中struct/union/class内存对齐
struct/union/class内存对齐原则有四个:
1).数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员存储的起始位置要从该成员大小或者成员的子成员大小(只要该成员有子成员,比如说是数组,结构体等)的整数倍开始(比如int在32位机为4字节, 则要从4的整数倍地址开始存储),基本类型不包括struct/uinon/class。
2).结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部"最宽基本类型成员"的整数倍地址开始存储.(struct a里存有struct b,b里有char,int ,double等元素,那b应该从8的整数倍开始存储.)。
3).收尾工作:结构体的总大小,也就是sizeof的结果,.必须是其内部最大成员的"最宽基本类型成员"的整数倍.不足的要补齐.(基本类型不包括struct/class/uinon)。
4).sizeof(union),以结构里面size最大元素为union的size,因为在某一时刻,union只有一个成员真正存储于该地址。
实例解释:下面以class为代表
No.1
class Data
{
char c;
int a;
}; cout << sizeof(Data) << endl;
No.2
class Data
{
char c;
double a;
}; cout << sizeof(Data) << endl;
显然程序No.1 输出的结果为 8 No.2 输出的结果为 16 .
No.1最大的数据成员是4bytes,1+4=5,补齐为4的倍数,也就是8。而No.2为8bytes,1+8=9,补齐为8的倍数,也就是16。
No.3
class Data
{
char c;
int a;
char d;
}; cout << sizeof(Data) << endl;
No.4
class Data
{
char c;
char d;
int a;
}; cout << sizeof(Data) << endl;
No.3运行结果为 12
No.4运行结果为 8
class中的数据成员放入内存的时候,内存拿出一个内存块来,数据成员们排队一个一个往里放,遇到太大的,不是把自己劈成两半,能放多少放多少,而是等下一个内存块过来。这样的话,就可以理解为什么No.3,No.4两端的代码输出结果不一样了,因为左边是1+(3)+4+1+(3)=12,而右边是1+1+(2)+4=8。括号中为补齐的bytes。
No.5
class BigData
{
char array[33];
}; class Data
{
BigData bd;
int integer;
double d;
}; cout << sizeof(BigData) << " " << sizeof(Data) << endl;
No.6
class BigData
{
char array[33];
}; class Data
{
BigData bd;
double d;
}; cout << sizeof(BigData) << " " << sizeof(Data) << endl;
No.5和No.6运行结果均为: 48
在默认条件下,内存对齐是以class中最大的那个基本类型为基准的,如果class中有自定义类型,则递归的取其中最大的基本类型来参与比较。在No.5和No.6中内存块一个接一个的过来接走数据成员,一直到第5块的时候,BigData里只剩1个char了,将它放入内存块中,内存块还剩7个bytes,接下来是个int(4bytes),能够放下,所以也进入第5个内存块,这时候内存块还剩3bytes,而接下来是个double(8bytes),放不下,所以要等下一个内存快到来。因此,No.5的Data的size=33+4+(3)+8=48,同理No.6应该是33+(7)+8=48。
顺便提一下Union: 共用体表示几个变量共用一个内存位置,在不同的时间保存不同的数据类型和不同长度的变量。在union中,所有的共用体成员共用一个空间,并且同一时间只能储存其中一个成员变量的值。
以上内容部分转载自http://www.cnblogs.com/biyeymyhjob/archive/2012/09/07/2674992.html
拓展:
一、32位操作系统下各种数据类型所占的字节数
1、整型
int 4字节
long int 4字节
short int 2字节
unsigned long int 4字节
unsigned short int 2字节
2、字符型
char 1字节
unsigned char 1字节
3、浮点型
float 4字节
double 8字节
long double 8字节
unsigned long double 8字节
unsigned double 4字节
4、字符串型
string 32字节
5、指针类型
所有类型的指针都是 4字节 (但是在64位下为8字节)
二、字节对齐原则
在系统默认的对齐方式下:每个成员相对于这个结构体变量地址的偏移量正好是该成员类型所占字节的整数倍,且最终占用字节数为成员类型中最大占用字节数的整数倍。
三、C++类中的数据成员也遵循以上对齐原则,即:
1.在不考虑(或者说在没有)虚函数和虚继承的情况下,sizeof(自定义类)也按照类似上面的方式来计算。
2.但如果一个类拥有虚函数或者虚继承,则在数据成员的基础上相当于多一个指针类型的数据成员(位置在所有数据成员的前面),最后计算时加上即可。
3.静态(static)成员不在计算范围。
[简言之,类的大小与成员变量(非static数据成员变量)和虚函数指针有关(注意:虚函数中有一个指向虚函数列表的指针,无论有多少个虚函数都是占用一个字节的大小)]
4.如果一个类或者结构体不含有任何数据成员,且无虚函数以及虚继承,则sizeof()结构为1。
四、为什么要进行字节对齐?
《Windows核心编程》里这样说:当CPU访问正确对齐的数据时,它的运行效率最高,当数据大小的数据模数的内存地址是0时,数据是对齐的。例如:WORD值应该是总是从被2除尽的地址开始,而DWORD值应该总是从被4除尽的地址开始,数据对齐不是内存结构的一部分,而是CPU结构的一部分。当CPU试图读取的数值没有正确的对齐时,CPU可以执行两种操作之一:产生一个异常条件;执行多次对齐的内存访问,以便读取完整的未对齐数据,若多次执行内存访问,应用程序的运行速度就会慢。
可参考webary的blog:http://www.cnblogs.com/webary/p/4721017.html
C/C++中struct/union/class内存对齐的更多相关文章
- Net的struct的内存对齐问题
很少有人谈起struct的内存对齐问题, 就是在很多C#书中, 也很少提及. 但在实际应用中, 如果不注意内存对齐, struct比较大的话, 则会浪费一定的内存. 先从一个实例看起. publ ...
- c++编程思想(三)--c++中c 续,重点sizeof和内存对齐
之前理论性的太多,下面就是代码及理论结合了 1.sizeof()是一个独立运算符,并不是函数,可以让我们知道任何变量字节数,可以顺带学一下struct,union,内存对齐 内存对齐:为了机器指令快速 ...
- Go中由WaitGroup引发对内存对齐思考
转载请声明出处哦~,本篇文章发布于luozhiyun的博客:https://www.luozhiyun.com 本文使用的go的源码时14.4 WaitGroup使用大家都会,但是其中是怎么实现的我们 ...
- c++中类对象的内存对齐
很多C++书籍中都介绍过,一个Class对象需要占用多大的内存空间.最权威的结论是: *非静态成员变量总合.(not static) *加上编译器为了CPU计算,作出的数据对齐处理.(c语言中面试中经 ...
- (转)c/c++内存对齐问题
struct/class/unio内存对齐: http://blog.csdn.net/microsues/article/details/6140329 class函数占用字节数问题: http:/ ...
- 【转】C/C++ struct/class/union内存对齐
原文链接:http://www.cnblogs.com/Miranda-lym/p/5197805.html struct/class/union内存对齐原则有四个: 1).数据成员对齐规则:结构(s ...
- <转> Struct 和 Union区别 以及 对内存对齐方式的说明
转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...
- C语言中内存对齐规则讨论(struct)
C语言中内存对齐规则讨论(struct) 对齐: 现代计算机中内存空间都是按着byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地 ...
- 内存对齐与ANSI C中struct型数据的内存布局 【转】
转自:http://blog.chinaunix.net/uid-25909619-id-3032209.html 当在C中定义了一个结构类型时,它的大小是否等于各字段(field)大小之和?编译器将 ...
随机推荐
- MySql数据库约束
<MySQL技术内幕:InnoDB存储引擎>本书从源代码的角度深度解析了InnoDB的体系结构.实现原理.工作机制,并给出了大量实践,本着将书读薄的思想,循序渐进的记录对本书学习的读书笔记 ...
- 数据处理之pandas库
1. Series对象 由于series对象很简单,跟数组类似,但多了一些额外的功能,偷个懒,用思维导图表示 2. DaraFrame对象 DataFrame将Series的使用场景由一维扩展到多维, ...
- RabbitMQ和Kafka可靠性
RabbitMQ和Kafka可靠性 https://www.cnblogs.com/haolujun/p/9641840.html 我们通过前文知道,RabbitMQ的队列分为master queue ...
- Mysql事件的创建和使用
1.查看事件是否开启SHOW VARIABLES LIKE 'event_scheduler'; 2.开启事件SET GLOBAL event_scheduler = ON; 3.创建事件DELIMI ...
- DCloud-wap2app:杂项
ylbtech-DCloud-wap2app:杂项 1.返回顶部 2.返回顶部 3.返回顶部 4.返回顶部 5.返回顶部 6.返回顶部 7.返回顶部 8.返回顶部 ...
- 人脑和CPU
人类的数学运算没有计算机快是因为神经信号速度没有电信号快吗,电信号是光速吧. 不过人类的cpu大脑和存储硬盘和内存超过目前计算机n条街,虽然传输速度慢,但是传输量也是大的,其实计算机就是根据人脑设计的 ...
- 本地测试html文件时CSS效果显示, 但是当django的服务器上运行时效果不显示
本地测试时各种效果都显示, 但是当在django服务器上测试时, 效果却不显示, 原因是我将css文件放在一个static文件夹里, 没有在settings中设置static_dir选项.将stati ...
- HDLM命令dlnkmgr详解之五_set
set命令用来设置HDLM的操作环境及参数. set操作设置的大部分是dlnkmgr view -sys命令中显示的参数值 命令格式 dlnkmgr set { -lb on [ -lbtype { ...
- HDLM命令dlnkmgr详解之二__help/clear
1.help操作 主要显示命令的帮助信息. 显示所有操作的帮助信息 -bash-3.2# dlnkmgr help dlnkmgr: Format dlnkmgr { clear | help | o ...
- AJAX——XMLHttpRequest对象的使用
AJAX是web2.0即动态网页的基础,而XMLHttpRequest对象又是AJAX的核心.XMLHttpRequest对象负责将用户信息以异步通信地发送到服务器端,并接收服务器响应信息和数据 一. ...