C内存对齐

本文深入解析了内存对齐的概念及其在编程中的应用,通过具体示例解释了如何通过#pragmapack指令控制结构体成员的对齐方式,并分析了不同情况下结构体大小的变化。
#include <stdio.h>

#pragma pack(4)
struct test
{
	int a;
	char b;
//	char reserve1;
	short c;
	char d;
//	char reserve2[3];
};
#pragma pack()


int main(void)
{
	printf("pack(4)=%d\n", sizeof(test));
	struct test t[2];

	return 0;
}


上面代码在VC6.0环境中编写,接下来有三个问题:1、加上如代码所示的注释,最终程序输出多少?2、去掉代码中的注释,最终程序输出多少?3、去掉#pragma pack(4)和#pragma pack()语句后再运行程序,最终输出多少?

 

 

这里给出最终答案为:pack(4)=12

对!上面3个问题的答案均一样!这是为什么呢?

    首先,要明白上述代码要说明的一个问题即是题目所示——“内存对齐”,为什么要进行内存对齐呢?根本原因在于CPU访问数据的效率问题。

    对齐跟数据在内存中的位置有关。如果一个变量的内存地址正好位于它长度的整数倍,他就被称做自然对齐。比如在32位cpu下,假设一个整型变量的地址为0x00000004,那它就是自然对齐的。假设某个整型变量的地址不是自然对齐,比如为0x00000002,则CPU如果取它的值的话需要访问两次内存,第一次取从0x00000002-0x00000003的一个short,第二次取从0x00000004-0x00000005的一个short然后组合得到所要的数据,如果变量在0x00000003地址上的话则要访问三次内存,第一次为char,第二次为short,第三次为char,然后组合得到整型数据。而如果变量在自然对齐位置上,则只要一次就可以取出数据。

    回到上面问题,首先对于#pragma pack伪指令语句,其意义在于声明在其下定义的结构体变量的对齐方式,程序中#pragma pack(4),即表达下面的结构体中的变量以4字节对齐,而#pragma pack()意思为取消对齐方式,它们是成对出现。当然如果在程序中只使用#pragma pack(4)也是可以的,那就是说明在本源文件中,该伪指令下的结构均为4字节对齐方式。至于第3个问题为什么取消和加上这两个伪指令结果都一样,是因为VC6.0编译器默认为4字节对齐方式。接下来分析下第1个问题,为什么会输出12?首先在x86的32位机器上我们要知道如下信息:

sizeof(char) = 1;

sizeof(short) = 2;

sizeof(int) = 4;

sizeof(float) = 4;

sizeof(double) = 8;

那接下来就好办了,在test结构体中定义了4个变量,第一个int型变量a显然占4个字节,第二个char型变量b占1个字节,第三个short型变量c占2个字节,第四个char型变量d占1个字节。总的字节数为:4+1+2+1 = 8。不对,明明输出是12啊?这里即是内存对齐搞的鬼了,假如该结构地址为0x00000000,那么第一个变量a的由于占4个字节,则其存储的区域为0x00000000~0x00000003对于第二个变量b,其本身占用1个字节,其占用的地址为:0x00000004;第三个变量c,其本身占用2个字节,复核0x00000006%2=0,则其应占用的地址为0x00000006~0x00000007,地址0x00000005需空出;对于第四个变量d,其本身占用1个字节,则其占用地址为0x00000008,因此总的有效占用字节为:4+2+2+1=9,为什么还是不是12呢?注意由于结构与结构之间还存在对齐,因此在该结构体末尾需加上3个字节补齐,即总的字节为12。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值