内存对齐(一)

   昨天做腾讯的笔试题,有两道是内存对齐问题,之前也看过,不过理解不够深刻,今天看了下前人总结,也小小的总结一下.

首先说说为什么要有内存对齐

1.内存对齐原因:

  (1):平台原因:不是所有的硬件平台都能访问任意地址的的任意数据的,某些硬件只能在某些地址取出某些特定类型的数据(百科).

  (2):性能原因:数据结构(尤其是栈)应该尽可能地在自然边界上对齐。原因在于,为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问.

PS:每个特定平台上的编译器都有自己的默认“对齐系数”(也叫对齐模数)。程序员可以通过预编译命令#pragma pack(n), n=1,2,4,8,16来改变这一系数,其中的n就是你要指定的“对齐系数”。默认:vc==8, gcc==4

2.对齐规则:

  (1)数据成员对齐规则:结构(struct)(或联合(union))的数据成员,第一个数据成员放在offset为0的地方,以后每个数据成员的对齐按照 #pragma pack指定的数值和这个数据成员自身长度中,比较小的那个进行。

  (2)结构(或联合)的整体对齐规则:在数据成员完成各自对齐之后,结构(或联合)本身也要进行对齐,对齐将按照#pragma pack指定的数值和结构(或联合)最大数据成员长度中,比较小的那个进行。

  (3)结合1、2推断:当#pragma pack的n值等于或超过所有数据成员长度的时候,这个n值的大小将不产生任何效果。

http://www.cppblog.com/cc/archive/2006/08/01/10765.html  这里面有内存对齐的形象展示.

下面是我在VC 6.0上的实验测试:

#include<stdio.h>

#pragma pack (4) /*结构体中的每个成员的起始地址都会是2的整数倍*/

struct X1
{
	char a;
	int b;
	__int64 i;
}x1;

struct X2
{
	char a;
	__int64 i;
	int b;
}x2;

struct X3
{
	__int64 i;
	char a;
	int b;
}x3;

void test_pragma_pack_4()
{
	printf("sizeof(x1) = %d, &a = %x, &b = %x, &i = %x\n", sizeof(x1), &(x1.a), &(x1.b), &(x1.i));
	printf("sizeof(x2) = %d, &a = %x, &i = %x, &b = %x\n", sizeof(x2), &(x2.a), &(x2.i), &(x2.b));
	printf("sizeof(x3) = %d, &i = %x, &a = %x, &b = %x\n", sizeof(x3), &(x3.i), &(x3.a), &(x3.b));
}

int main()
{
	test_pragma_pack_4();
	return 0;
}


 
输出: 

sizeof(x1) = 16, &a = 427e78, &b = 427e7c, &i = 427e80
sizeof(x2) = 16, &a = 427e88, &i = 427e8c, &b = 427e94
sizeof(x3) = 16, &i = 427e98, &a = 427ea0, &b = 427ea4
Press any key to continue

分析:

1:由于x1.a是char类型占1个字节,放在了地址为0x427e78处,而x1.b是int类型,占4个字节,因此以4个字节方式对齐,x1.b的地址为0x427e7c=0x427e78 + 0x000003, 而x1.i是__int64类型,占8个字节,因此用8与设置的对齐模数4比较:8>4,因此x1.b与x1.i之间以4字节对齐,x1.i的地址为0x427e80 = 0x427e7c + 0x000003. sizeof(x1) = 16

2:由于x2.a是char类型占1个字节,放在了地址0x427e88处,而x2.i是__int64类型,占8个字节,8>4,0x427e88 + 0x000003 = 0x427e8c

,而x2.b是int类型占4个字节,i占8个字节是4的整数倍,因此可直接对齐,x2.b的地址为0x427e94.

3:由于x3.i是__int64类型,占8个字节,地址为0x427e98,而x3.a是char类型,占1个字节,8是1的整数倍,已经对齐,x3.a的地址为0x427ea0, x3.b是int类型,占4个字节,之前共占9个字节,不是4的整数倍,因此需要做对齐处理,x3.b的地址为0x427ea0 + 0x000003= 0x427ea4.

以上是我今天总结,有错误的地方希望多指正,正在学习中...



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值