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; }:第二种:有结构体名,并声 ...
随机推荐
- 动态属性ExpandoObject
1.动态创建对象及其属性ExpandoObject 查看ExpandoObject的定义:
- WordPress熊掌号页面改造,自动发布
写在前面的话: 有很多小伙伴刚进入WordPress,对很多东西还不太了解,比如:有的主题很挑剔,对于有些插件不兼容,但是呢对于这个功能有不可或缺.所以,这时候就需要我们自己手动修改或者添加代码,来实 ...
- 通过机智云APP来学习安卓
效果非常之好,安卓6.0之后就进行了动态授权.按照网上的视频一步一步调试的非常成功,非常舒服.
- oracle数据库定时备份
现有需求,设计一批处理文件,实现周一全部备份,周二周三周五周六增量备份,周四周日累计备份.并且每日将上个月本日数据删除(如今日8月7号,则删除7月7号的数据).并将备份压缩以减小所占空间. 思路: 备 ...
- 前端JavaScript入门——JavaScript变量和操作元素
变量JavaScript 是一种弱类型语言,javascript的变量类型由它的值来决定. 定义变量需要用关键字 ‘var’: var a = 123; var b = 'asd'; //同时定义多个 ...
- Linux 中ifconfig和ip addr命令查看不到ip解决方法
1.输入查看ip的命令ifconfig或ip addr,查不到ip 2.查看ens33网卡配置,输入 vi /etc/sysconfig/network-scripts/ifcfg-ens33 将ON ...
- 如何在mybatis中引用java中的常量和方法
转自:http://www.68idc.cn/help/jiabenmake/qita/20140821125261.html 在mybatis的映射xml文件调用java类的方法: 1. SELEC ...
- JS模拟CSS3动画-贝塞尔曲线
一.什么是贝塞尔曲线 1962年,法国工程师皮埃尔·贝塞尔(Pierre Bézier),贝塞尔曲线来为为解决汽车的主体的设计问题而发明了贝塞尔曲线.如今,贝赛尔曲线是计算机图形学中相当重要的一种曲线 ...
- Redis系列(六)--为什么这么快?
Redis作为一个基于key-value的NoSQL数据库,最显著的特点存取速度非常快,官方说可以达到10W OPS,但是Redis为何这么快? 1.开发语言 Redis使用C语言进行编写的,而Uni ...
- bzoj 4026 dC Loves Number Theory 主席树+欧拉函数
题目描述 dC 在秒了BZOJ 上所有的数论题后,感觉萌萌哒,想出了这么一道水题,来拯救日益枯竭的水题资源.给定一个长度为 n的正整数序列A,有q次询问,每次询问一段区间内所有元素乘积的φ(φ(n)代 ...