整数边界对齐方式_关于结构体边界对齐的问题

本文详细介绍了结构体成员的对齐规则,包括普通数据成员、结构体成员和结构体大小的对齐原则,并通过实例解析了内存布局。同时讨论了在#pragma pack宏影响下的对齐方式变化。
摘要由CSDN通过智能技术生成

首先,在没有#pragma pack的情况下,要遵循如下几个原则:

原则1、普通数据成员对齐规则:第一个数据成员放在offset为0的地方(可假设起始位置为0,事实上,结构体成员要从其内部最大元素大小的整数倍地址处开始存储);以后每个数据成员存储的起始地址要从该成员大小的整数倍开始(比如int在32为机器上为4字节,则要从4的整数倍地址开始存储)

原则2、结构体成员对齐规则:如果一个结构体成员里有某些结构体成员,该结构体成员从其内部最大元素大小的整数倍地址处开始存储(struct

a里面有struct b,b里面有char,int,double等,那么b应该从8的整数倍地址处开始存储)

原则3、结构体大小对齐规则:结构体的大小也就是sizeof对应的结果,必须是其内部成员中最大(复合类型成员取子成员就算

,而不能将其当做整体)的对齐参数的整数倍,不足的要补齐。

补充一点,如果数组作为结构体成员,比如:char

a[3]。它的对齐方式和分别写3个char是一样的,也就是说它还是按1个字节对齐。如果写: typedef char

Array3[3];Array3这种类型的对齐方式还是按1个字节对齐,而不是按它的长度3对齐。如果共用体作为结构体成员,则该共用体成员要从其内部最大元素大小的整数倍地址开始存储,如果是枚举类型作为结构体成员,则该枚举类型默认从int大小的整数倍地址开始存储

还有一种对齐原则,和上面三条一致,可以参考着理解。

成员对齐有一个重要的条件,即每个成员按自己的方式对齐。其对齐的规则是,每个成员按其类型的对齐参数(通常是这个类型的大小)和指定对齐参数(这里默认是8字节)中较小的一个对齐。并且结构的长度必须为所用过的所有对齐参数的整数倍,不够就补空字节。

这三个原则具体怎样理解呢?我们看下面几个例子,通过实例来加深理解。

例1:struct

{

short a1;

short a2;

short a3;

}A;

struct{

long a1;

short a2;

}B;

sizeof(A) = 6; 这个很好理解,三个short都为2。

sizeof(B) = 8;

这个比是不是比预想的大2个字节?long为4,short为2,整个为8,因为原则3。

例2:struct A{

int a;

char b;

short c;

};

struct B{

char b;

int

a;

short c;

};

sizeof(A) = 8;

int为4,char为1,short为2,这里用到了原则1和原则3。

sizeof(B) = 12;

是否超出预想范围?char为1,int为4,short为2,怎么会是12?还是原则1和原则3。

深究一下,为什么是这样,我们可以看看内存里的布局情况。

a b c

A的内存布局:1111, 1*,11

b a c

B的内存布局:1***,1111,11**

其中星号*表示填充的字节。A中,b后面为何要补充一个字节?因为c为

short,其起始位置要为2的倍数,就是原则1。c的后面没有补充,因为b和c正好占用4个字节,整个A占用空间为4的倍数,也就是最大成员int类型的倍数,所以不用补充。B中,b是char为1,b后面补充了3个字节,因为a是int为4,根据原则1,起始位置要为4的倍数,所以b后面要补充3个字节。c后面补充两个字节,根据原则3,整个B占用空间要为4的倍数,c后面不补充,整个B的空间为10,不符,所以要补充2个字节。

再看一个结构中含有结构成员的例子:

例3:struct A{

int a;

double b;

float c;

};

struct

B{

char e[2];

int f;

double

g; short h;

struct A i;

};

sizeof(A) = 24;

这个比较好理解,int为4,double为8,float为4,总长为8的倍数,补齐,所以整个A为24。

sizeof(B) = 48; 看看B的内存布局。

e f g h i B 的内存布局:11* *,1111,11111111, 11 * * * * * *,1111* * * *, 11111111,

1111 * * *

* 。 i其实就是A的内存布局。i的起始位置要为8(此处我个人觉得应该为8的倍数,

http://blog.csdn.net/b_h_l/article/details/7738217原引用处为24,)的倍数,所以h后面要补齐。把B的内存布局弄清楚,有关结构体的对齐方式基本就算掌握了。

以上讲的都是没有#pragma pack宏的情况,如果有#pragma

pack宏,对齐方式按照宏的定义来。比如上面的结构体前加#pragma pack(1),内存的布局就会完全改变。sizeof(A) =

16; sizeof(B) = 32;有了#pragma pack(1),内存不会再遵循原则1和原则3了,(是否还遵循原则2?目前还没搞清楚)按1字节对齐。没错,这不是理想中的没有内存对齐的世界吗。

a b c

A的内存布局:1111,11111111,1111

e f g h i B的内存布局:11,1111,11111111,11,1111, 11111111,

1111

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值