C++成员对齐方式探讨
本文參考了《高质量程序设计指南——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++成员对齐方式探讨的更多相关文章
- 关于arm处理器 内存编址模式 与 字节对齐方式 (转)
转自:http://bavon.bokee.com/5429805.html 在x86+Linux上写的程序,在PC机上运行得很好.可是使用ARM的gcc进行交叉编译,再送到DaVinci目标板上运行 ...
- C# 使用 StructLayoutAttribute 时 C# /C++ 内存空间分配与成员对齐问题
1. 使用场景 公共语言运行时控制数据字段的类或结构在托管内存中的物理布局.但是,如果想要将类型传递到非托管代码,需要使用 StructLayout 属性. 2. 内存分配问题. 如果不显示的设置内存 ...
- C语言中内存对齐方式
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
- struct的成员对齐问题-结构体实际大小问题
struct的成员对齐 注意:为了方便说明,等号左边是每个数据单独所占长度,右边是最终空间大小,以字节为单位. 一.什么时间存在对其问题:(32位机对齐方式是按照4字节对其的,以下所有试验都是在32位 ...
- C++ 学习笔记3,struct长度測试,struct存储时的对齐方式
之所以专门为struct的长度写一篇測试,是由于原来c++对于struct的变量, 在分配内存的时候,c++对struct有一种特殊的存储机制. 看以下的測试: 一.在Windows7 32bit , ...
- 从零开始学C++之IO流类库(四):输出流格式化(以操纵子方式格式化 以ios类成员函数方式格式化)
一.以操纵子方式格式化 数据输入输出的格式控制使用系统头文件<iomanip>中提供的操纵符.把它们作为插入操作符<<的输出对象即可.如setiosflags.setw.set ...
- 输出流格式化(以操纵子方式格式化,以ios类成员函数方式格式化)
一.以操纵子方式格式化 数据输入输出的格式控制使用系统头文件<iomanip>中提供的操纵符.把它们作为插入操作符<<的输出对象即可.如setiosflags.setw.set ...
- <转> Struct 和 Union区别 以及 对内存对齐方式的说明
转载地址:http://blog.csdn.net/firefly_2002/article/details/7954458 一.Struct 和 Union有下列区别: 1.在存储多个成员信息时,编 ...
- C/C++ struct定义、声明、对齐方式
一.定义/声明方式 第一种:仅有结构体名,不定义/声明变量 struct MyStruct { int i: char a[10]; double b; }:第二种:有结构体名,并声 ...
随机推荐
- 6.12---Swagger中paramType---swagger的RequestParam和ApiImpliciParam----Example中方法带有selective
paramType:表示参数放在哪个地方 header-->请求参数的获取:@RequestHeader(代码中接收注解) query-->请求参数的获取:@RequestPa ...
- 系统资源监控--windows
前言: 系统资源监控一般监控系统的CPU,内存,磁盘和网络.系统分为windows和Linux.本篇主要记录windows. Windows的监控相对与Linux监控工具来说比较简单,更多的是查看wi ...
- Windows开启ICMP包回显
- Windows提高_1.1内核对象
内核对象 什么是内核对象? 内核对象本质上是一个结构体,我们不能直接的操作一个内核对象,需要通过操作系统提供的一系列函数和我们使用的内核对象句柄对它进行一系列的修改. 如何操作内核对象? 创建一个内核 ...
- CLISTCTRL 获取点击列
CListCtrl中的HitTest.SubItemHitTest的用法 2HitTest:得到当前鼠标位置的Item 其实关键是要有ScreenToClient这个函数的使用,我先前没有用这个函数, ...
- xmpp消息回执(6)
原始地址:XMPPFrameWork IOS 开发(七)消息回执 请参考:XEP-0184协议 协议内容: 发送消息时附加回执请求 <message from='northumberland@s ...
- C语言scanf函数详细解释(转载)
原文地址:https://blog.csdn.net/21aspnet/article/details/174326 scanf 函数名: scanf 功 能: 执行格式化输入 用 法: int sc ...
- MySQL5
MySQL数据库5 mysqldump备份恢复数据库 冷备份还原数据库 逻辑卷快照备份还原数据库 xtrabackup备份还原数据库 1. 备份和恢复概述 适用场景 硬件故障.软件故障.自然灾害.黑客 ...
- out对象的使用
out对象的使用 制作人:全心全意 out对象用于在Web浏览器内输出信息,并且管理应用服务器上的输出缓冲区.在使用out对象输出数据时,可以对数据缓冲区进行操作,及时清除缓冲区中的残余数据,为其他的 ...
- 59.关系型与document类型数据模型对比
现假设有如下两个类: class Department(object): def __init__(self, dept_id, name, desc, employees=[]): self.dep ...