本文參考了《高质量程序设计指南——C++/C语言》一书

有不妥之处恳请指正

一、自然对齐

某些基于RISC(精简指令集)的CPU比方SPARC、PowerPC等。採用高字节和高字在低地址存放、低字节和低字在高地址存放的大端模式存储。而且把最高字节的地址作为变量的首地址。

在这样的自然的存储格式中,要求变量在内存中的存放位置必须自然对齐,否则CPU会报告异常。所谓自然对齐,就是基本数据类型(主要是short、int、double)的变量不能简单地存储于内存中的随意地址处。它们的起始地址必须可以被它们的大小整除。

比如。在32位平台下,int和指针类型变量的地址应该能被4整除。而short变量的地址应该都是偶数,bool和char则没有要求。所以。基于这样的CPU架构的平台,编译器将依照自然对齐的要求来为每一个变量生成逻辑地址,C++/C编译器亦如此。

而Intel系列CPU採用小端模式来存放基本类型变量,即低字节和低字在低地址存放、高字节和高字在高地址存放。而且把最低字节的地址作为变量的首地址。在Intel系列CPU这样的硬件平台上。并不严格要求基本数据类型变量在内存中必须自然对齐,相同也不会要求复合类型变量必须自然对齐。可是VC++在处理程序时,为了提高CPU的处理速度,对复合类型变量做了成员对齐处理。

二、成员对齐

VC++在处理复合数据类型成员变量时默认遵循下面三种原则:

(1)    复合类型对象的首地址要能被占用字节数最多的成员变量的字节数整除。

(2)    复合类型对象占用的内存空间大小要能被占用字节数最多的成员变量的字节数整除。

(3)    各成员变量存放的起始地址相对于复合结构的起始地址的偏移量必须为该变量的类型所占用的字节数的倍数。

举比例如以下:

struct exm

{

bool a;

double b;

bool c;

};

它是怎么存储的?

首先,在内存中找一个能被8整除的起始地址。然后分配24个字节。

为什么是24个而不是10个?或者是16个?

这是由于原则(3)的缘故,变量b占8个字节,那么它相对于结构的起始地址的偏移量必须为8的倍数,因此尽管a仅仅占一个字节,但后面会补上7个字节。

那么为什么变量c也占8个字节啊?这是由于原则(2)的缘故。由于在结构体exm中。占用字节数最多的是变量b。8个字节,所以exm占用的空间大小应能被8整除,如今a和b已经占用16个字节了,而c至少要占用一个字节,因此会在c后补上7个字节,变成24个字节。

把exm成员调换一下。变为:

struct exm

{

double b。

bool a。

bool c;

};

它的大小就变成16个字节了。

当然,我们也能够在程序中指定对齐方式。这时上述原则将不再成立。假设在程序中指定对齐方式。则对于复合结构中的变量,假设占用空间不足指定对齐字节。且假设依照默认对齐方式占用的空间将比指定的对齐方式大,则将按指定对齐方式补足,比如:

#pragmapack(4) //依照4字节边界对齐

struct exm

{

bool a;

double b;

bool c;

};

在VS2010中,它占用16个字节空间。

分析:变量a假设依照默认对齐方式要占8位,但它本身是bool型变量,占一位,指定对齐方式为4字节对齐,则a将被补齐为4字节。同理变量c也一样。

把exm成员换一下位置:

#pragmapack(4) //依照4字节边界对齐

struct exm

{

double b;

bool a;

bool c。

};

则exm占12位。

C++成员对齐方式探讨的更多相关文章

  1. 关于arm处理器 内存编址模式 与 字节对齐方式 (转)

    转自:http://bavon.bokee.com/5429805.html 在x86+Linux上写的程序,在PC机上运行得很好.可是使用ARM的gcc进行交叉编译,再送到DaVinci目标板上运行 ...

  2. C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题

    1. 使用场景 公共语言运行时控制数据字段的类或结构在托管内存中的物理布局.但是,如果想要将类型传递到非托管代码,需要使用 StructLayout 属性. 2. 内存分配问题. 如果不显示的设置内存 ...

  3. C语言中内存对齐方式

    一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...

  4. struct的成员对齐问题-结构体实际大小问题

    struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...

  5. C++ 学习笔记3,struct长度測试,struct存储时的对齐方式

    之所以专门为struct的长度写一篇測试,是由于原来c++对于struct的变量, 在分配内存的时候,c++对struct有一种特殊的存储机制. 看以下的測试: 一.在Windows7 32bit , ...

  6. 从零开始学C++之IO流类库(四):输出流格式化(以操纵子方式格式化 以ios类成员函数方式格式化)

    一.以操纵子方式格式化 数据输入输出的格式控制使用系统头文件<iomanip>中提供的操纵符.把它们作为插入操作符<<的输出对象即可.如setiosflags.setw.set ...

  7. 输出流格式化(以操纵子方式格式化,以ios类成员函数方式格式化)

    一.以操纵子方式格式化 数据输入输出的格式控制使用系统头文件<iomanip>中提供的操纵符.把它们作为插入操作符<<的输出对象即可.如setiosflags.setw.set ...

  8. <转> Struct 和 Union区别 以及 对内存对齐方式的说明

    转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...

  9. C/C++ struct定义、声明、对齐方式

    一.定义/声明方式 第一种:仅有结构体名,不定义/声明变量 struct MyStruct {  int i:     char a[10];     double b; }:第二种:有结构体名,并声 ...

随机推荐

  1. 93. [NOIP2001] 数的划分

    问题描述 将整数n分成k份,且每份不能为空,任意两种方案不能相同(不考虑顺序). 例如:n=7,k=3,下面三种分法被认为是相同的. 1,1,5; 1,5,1; 5,1,1; 问有多少种不同的分法. ...

  2. python--12、数据库进阶

    SQL语句关键词: #再次不做过多介绍 使用INSERT实现数据的插入 UPDATE实现数据的更新 使用DELETE实现数据的删除 使用SELECT查询数据以及. #示例中department为部门表 ...

  3. js中取整数的方法

    1.取整的方法 Math.floor( ) Math 对象的方法--取比当前数值小的最大整数(下取整). Math.ceil( ) Math对象的方法--取比当前数值大的最小整数(上取整). Math ...

  4. StyleAI厚积薄发: Android网络图片数据传输

    在StyleAI上厚积了这么长时间,憋了这么久,本来想憋个更大的,不过还是薄发一次的好. 三.直接使用别人的工程 文章:Android学习之客户端上传图片到服务器 下载地址:https://downl ...

  5. (转)淘淘商城系列——使用Jedis操作集群

    http://blog.csdn.net/yerenyuan_pku/article/details/72862084 通过上文的学习,我相信大家应该已经知道如何搭建Redis集群了,本文我将为大家介 ...

  6. 搭建linux环境:如何在vmware安装linux虚拟机??

    本来不想再整一遍的,奈何分布式压测呀,呀呀呀呀呀呀 1.安装linux虚机 (1)在桌面上双击VMware Workstation图标后启动虚拟机,鼠标单击文件,选择新的虚拟机: (2)单击“next ...

  7. ThinkPHP---thinkphp文件加载

    [一]文件加载在ThinkPHP里提供了三种方式 实际开发里,文件加载方式一般以第一种为主(通过函数库形式自动加载,此时我们仅仅需要定义文件和函数) (1)函数库形式加载 函数库分3种级别,系统函数库 ...

  8. Linux(Centos7) 设置静态IP

    关于虚拟机 这里使用Centos7为例,因为linux是安装在在虚拟机中,这里先看一下虚拟机的网络适配器: 这里我使用的NAT模式,接着配置虚拟机的虚拟网络: 这里主要看一下VMnet8的设置: 这里 ...

  9. Microsoft SQL Server 存储过程

    Microsoft SQL Server 存储过程 TRIGGER DDL触发器:主要用于防止对数据库架构.视图.表.存储过程等进行的某些修改:DDL事件是指对数据库CREATE,ALTER,DROP ...

  10. springAOP源码解析-190313

    Spring相关笔记 SpringAOP讲解 子路老师讲解 spring与aspectj的区别答:它们的区别是 spring是动态加载 aspectj是静态加载,再编译过程就已经实现切面,此时会往代码 ...