C/C++:内存字节对齐详解

这篇博文其实是上一篇博文:C++笔试总结-面试笔试常考题型(一)指针-引用-宏定义-sizeof 的续篇,忽然发现这是一个问题,所以就整理了下,先看一段代码:

例1

#include "stdafx.h"
#include <iostream>
using namespace std;

struct A
{
	char a;
	long b;
	char c;
	double d;
};
struct B       //换一个顺序
{
	char a;
	char c;
	long b;
	double d;
};
int main(){
	cout << sizeof(A) << endl;
	cout << sizeof(B) << endl;
	return 0;
}
其输出结果为: 24 [换行] 16 ,不同样结构体包含相同的元素类型,为什么得到的长度不相同呢?这就 牵扯到 数据对齐 

1. 什么是数据对齐?

线代计算机中内存空间都是按照byte划分的,从理论上讲似乎对任何类型的变量的存储与访问都可以从任何地址开始,但是实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要给类型数据按照一定的规划在空间上排列,而不是顺序的一个个排列,这就是对齐。

2.对齐方式

就上面的例子来说,对齐方式为:我们的平台默认的对齐长队为4个字节,那么其对齐方式分别如下:

 

上图即是内存对齐的解析,为什么两种对齐方式不一样呢?我们的平台默认对齐长度为4个字节

  • 结构体A:结构体A中的元素顺序为char,long,char,double,其自身对齐长度为:1,4,1,8,内存存储数据的原则是:存放的首地址需整除数据本身长度。所以内存0地址存放char,0%1=0,在内存4开始存放long数据,占4个字节,所以4%4=0,紧接着放char,8%1=0,此时double自身对齐占8个字节,所以应该从16号内存开始存储double数据。故结构体A占24个字节
  • 结构体B:存放的元素类型顺序为:char,char,long,double,还是按照内存存放数据的原则,所以结构体B仅占16个字节
3. 自定义对齐长度
在VC中,我们可以用pack预处理来禁止对齐调整,下面的代码使得结构更加紧凑:
#include "stdafx.h"
#include <iostream>
using namespace std;

#pragma pack(2) /*指定按2字节对齐*/
struct C {
	char a;
	long b;
	char c;
	double d;
};
#pragma pack() /*取消指定对齐,恢复缺省对齐*/

int main(){
	cout << sizeof(C) << endl;
	return 0;
}
运行结果为: 16 ,因为我们设定对齐长度为2个字节,在结构体中,char自身对齐长度为1个字节,1 < 设定长度2,所以char的有效对齐长度为1个字节,第0号内存存放char,第二个变量long,自身对齐长度为4个字节,但是4 > 2, 所以有效对齐长度为2个字节,存放地址从第2号开始,因为第1号内存1%2=1而不等于0,所以从第2号内存开始,一直到第5号内存结束,第6号内存存放char元素,接下来的double 自身对齐长度为8个字节,但是8>2,所以有效长度为2,因为7%2=1(不等于0),所以从第8号内存开始存储double元素,一直到第15号内存,所以结构体C占用16个字节。
我们得到在结构体或者类中, 有效对齐长度是 自身对齐长度与设定对齐长度中较小的那一个


参考文献:
1. 程序员面试宝典
2. 数据对齐详解 bakari

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值