C++字节对齐问题
关于C++字节对齐问题
这两天写解析SWF文件的程序,在结构体指针和从文件里读出来的进行转换的时候遇到一些问题,就是有一个struct A,比如:
struct A
{
char flag;
int length;
int id;
....
};
然后一个飘逸的 struct A *a = (struct A*)buffer; // 世界一下清静咯
可惜在输出a中的成员的时候却发现老是不对,百思不得起解。今晚一想,可能是因为C++的字节对齐问题,所以直接就百度了一些
C++的字节对齐。看到以下这篇文章说的挺清晰的,就转了过来。
________________________________________________________________________________________________________
近期研究C++的数据类型和数据大小时发现,字节对齐实际上是一个C/C++程序猿无法忽视的一个问题.所以进行了初步的研究.
1.为什么会出现内存对齐问题-从x86 CPU架构说起
相信绝大多数计算机系和软件学院的学生都学过计算机组成原理这门基础课程,所以不作入门引导了,没有相关背景的能够补补相关课程资料.常有人问我,既然是按字节寻址方式,为何会出现字节对齐问题呢?难道是内存不是连续的吗?
这个问题实际上和CPU与内存的连接方式有关,我们知道CPU会通过地址总线Address BUS与CPU连接用于寻址,用Data Bus数据总线连接用于获取数据,而内存一般是RAM构成的复杂阵列。
对于这个RAM阵列(实际内存可能更复杂,可是原理类似), 前16个内存地址排列相应内存单元关系例如以下:

对比上图,是不是发现,对于每一个内存操作周期,每一个地址实际上能够读取4个bytes的数据呢,那么如果你有一个int型的数据存储在地址1或者2或者 3,那么,是不是一个CPU内存时钟周期不够取出这个数据呢?这样是不是效率会非常低下?这也就是为什么我们须要内存对齐了,尽管现代CPU和编译器已经对 此做了非常多优化,可是C/C++因为特殊性,程序猿必须了解这个细节.
2.C/C++内存对齐的方式
C/C++中的结构/类的成员变量在对齐在内存中的排列是与它们摆放的先后顺序相关的,先看看以下的结构
1 struct malign_a
2 {
3 char a;
4 short b;
5 char c;
6 int d;
7 };
这个结构的sizeof(malign_a)是多少呢?1+2+1+4 =8?吗?这个实际上不正确,那么,怎样对齐的呢?
因为char是1个byte,所以无论他在什么位置,都能够用一个内存周期读出数据,short是半个字也就是2 bytes,这个时候假如它的地址是某个边界位置上,那么,也须要两个内存周期来读取,以此类推.所以,内存对齐就是增加填充padding无意义的数据 来保证某个数据位于一个能够通过最少内存周期的位置,比方double型仅仅有地址位于%4等于0的位置,才干保证2个周期读出.
同一时候对于每一个详细平台,不同的编译器有不同的指定的对齐模式,比方C/C++能够通过
1 #pragma pack(n) //n为1,2,4,8,16等
来指定对齐.当然,一般x86 32位机器下,都是默认4字节对齐的.这个n也称为对齐模数.
对齐策略例如以下:
1.结构体成员对齐:按某成员数据本身大小以及指定大小中较小者对齐
2.结构体总体对齐:按全部成员中最大者和对齐模数中较小者对齐
所以上述结构体按默认对齐方式例如以下:
1.a是char类型,能够在任何位置,位于位置0
2.b是short类型,2比默认的4小,所以按2字节对齐,所以在a后面填充1个字节,b必须位于位置2,占两个字节
3.c是char类型,位于位置4
4.d是int类型,4<=4,所以按4字节对齐,须要在c后面填充3个字节,位置为8
5.因为最大成员是4,默认是4,所以结构已经按4对齐,所以总字节数为12

再把原来的结构体成员位置修改一下:
1 struct malign_b
2 {
3 char a;
4 char c;
5 short b;
6 int d;
7 };
这个结构的大小为8,对齐步骤例如以下:
1.a是char类型,能够在任何位置,位于位置0
2.c是char类型,位于位置1
3.b是short类型,2比默认的4小,所以按2字节对齐,这时候恰好位于位置2
4.d是int类型,4 5.因为最大成员是4,默认是4,所以结构已经按4对齐,所以总字节数为8

最后为了加深理解,我们来看看以下这个结构按对齐模数2对齐时候的memory layout
01 #pragma pack(push)
02 #pragma pack(2)
03 struct malign_b
04 {
05 char a;
06 int d;
07 char c;
08 short b;
09 };
10 #pragma pack(pop)
它的大小为10,当指定为对齐模数2时候
1.因为a是char,1<2,位于位置0
2.因为d是int,4>2,所以按2字节对齐,所以必须在a后面填充一个字节,位于位置2,
3.c是char,位置为6
4.b是short,所以必须在c后面填充一个字节,位置为8
5.最大的是4,所以按2对齐,上述结果事实上已经总体是按2对齐,所以总数为10

我相信通过以上样例,应该能够熟悉字节对齐过程了,假设有不妥之处,敬请留言指出,谢谢.
原文链接:http://www.cnblogs.com/shihao/archive/2012/01/18/2325580.html
C++字节对齐问题的更多相关文章
- C语言:内存字节对齐详解[转载]
一.什么是对齐,以及为什么要对齐: 1. 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问, ...
- 字节对齐导致的iOS EXC_ARM_DA_ALIGN崩溃
本文原链接: http://www.cnblogs.com/zouzf/p/4455167.html 先看一下这个链接:http://www.cnblogs.com/ren54/archive/201 ...
- ACE的CDR中的字节对齐问题
大家应该都知道计算机中间都有字节对齐问题.CPU访问内存的时候,如果从特定的地址开始访问一般可以加快速度,比如在32位机器上,如果一个32位的整数被放在能被32模除等于0的地址上,只需要访问一次,而如 ...
- ARM字节对齐问题详解
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特定的内存地址访问,这 ...
- C语言之字节对齐
在C语言编程中,有时为了达到减少运行的时间的目的,需要浪费一些空间:而有时为了节省空间,使它的运行时间增长.而字节对齐则是为了访问效率,用空间换取时间. 要掌握字节对齐,首先得明确一下四个概念: 1. ...
- C ~ C语言字节对齐
1. 什么是对齐? 现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型 ...
- C语言的struct/union字节对齐
C语言的一大优势就是对内存空间的控制,当然,一般情况下对于开发人员来说都是透明的.看一个始终困扰初学者的问题:字节对齐! 先看四个重要的基本概念:1.数据类型自身的对齐值:对于char型数据,其自身对 ...
- C语言深入学习系列 - 字节对齐&内存管理
用C语言写程序时需要知道是大端模式还是小端模式. 所谓的大端模式,是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低地址中:所谓的小端模式,是指数据的低位保存在内存的低地址中,而数据的高 ...
- c++内存中字节对齐问题详解
一.什么是字节对齐,为什么要对齐? 现代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定类型变量的时候经常在特 定的内存地址 ...
随机推荐
- ASIFormDataRequest 登录
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL: [NSURL URLWithString: @"http: ...
- Linux makefile教程之使用变量五[转]
使用变量 ———— 在 Makefile中的定义的变量,就像是C/C++语言中的宏一样,他代表了一个文本字串,在Makefile中执行的时候其会自动原模原样地展开在所使 用的地方.其与C/C++所不同 ...
- js画线
<body> <div id="main"> </div> <div id="fd" style="filt ...
- Golang 做的几个跟性能有关的工具
1.Vegeta https://github.com/tsenart/vegeta Vegeta 是一个万能的 HTTP 负载测试工具,提供命令行工具和一个开发包. 使用方法: $ vegeta a ...
- HDU5800 To My Girlfriend 背包计数dp
分析:首先定义状态dp[i][j][s1][s2]代表前i个物品中,选若干个物品,总价值为j 其中s1个物品时必选,s2物品必不选的方案数 那么转移的时候可以考虑,第i个物品是可选可可不选的 dp[i ...
- js获取字符串最后一个字符代码
方法一:运用String对象下的charAt方法 charAt() 方法可返回指定位置的字符. 代码如下 复制代码 str.charAt(str.length – 1) 请注意,JavaScript ...
- 对人脑处理视觉的描述(摘《学习OpenCV(中文版)》)
人脑将视觉信号划分入很多个通道,将各种不同的信息输入你的大脑.你的大脑有一个关注系统,会根据任务识别出图像的重要部分,并做重点分析,而其他部分则分析得较少 .在人类视觉流中存在大量的反馈,但是目前我们 ...
- nagios监控远程主机服务可能出现的问题
1.使用插件NRPE监控命令不存在 在添加服务的时候,命令配置文件中需要传递一个参数,那么在监控服务配置文件中,需要添加一个!表示后面的为参数. 出现未定义的命令,查看被监控主机上的配置文件,添加监控 ...
- Basic Sorting Algorithms
*稳定指原本数列中相同的元素的相对前后位置在排序后不会被打乱 快速排序(n*lgn 不稳定):数组中随机选取一个数x(这里选择最后一个),将数组按比x大的和x小的分成两部分,再对剩余两部分重复这个算法 ...
- 50种方法优化SQL Server数据库查询
查询速度慢的原因很多,常见如下几种: 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 ...