结构体字节对齐

目录

结构体字节对齐意义

1、平台原因(移植原因)

 2、性能原因

结构体字节对齐方法

1、对齐值概念

1.1 自身对齐值

1.2 指定对齐值 

1.3 有效对齐值

1.4 结构体有效对齐值

2、对齐规则

2.1 规则一

2.2 规则二

3、对齐步骤(实操)

3、结构体嵌套

 编程应用

1、节省空间

2、节省时间

3、隐患

结构体字节对齐意义

1、平台原因(移植原因)

        不是所有的硬件平台都能访问任意地址上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常。(例如无法使用0x00000000地址处的空间)

 2、性能原因

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


结构体字节对齐方法

1、对齐值概念

  • 自身对齐值:数据类型本身的对齐值,例如char类型的自身对齐值是1,short类型是2;
  • 指定对齐值:编译器或程序员指定的对齐值;
  • 有效对齐值:自身对齐值和指定对齐值中较小的那个。
  • 结构体有效对齐值:其最大数据成员的自身对齐值。

1.1 自身对齐值

 

1.2 指定对齐值 

        指定对齐值:无预编译指令#pragma pack(n)就看默认CPU周期。

(1) CPU周期

        WIN  vs  qt  默认8字节对齐

        Linux 32位 默认4字节对齐,64位默认8字节对齐

(2) 预编译指令

        使用伪指令#pragma pack (n),C编译器将按照n个字节对齐。n = 1 2 4 8 16
        使用伪指令#pragma pack (),取消自定义字节对齐方式。

1.3 有效对齐值

        自身对齐值和指定对齐值中取最小值。

1.4 结构体有效对齐值

        结构体最大数据成员的自身对齐值。(包括嵌套中的结构体的最大成员)。

2、对齐规则

2.1 规则一

        存放成员的起始地址必须是该成员有效对齐值的整数倍。第一个成员为结构体起始地址。

2.2 规则二

        对于结构体本身,要将其补齐为结构体有效对齐值的整数倍。

3、对齐步骤(实操)

        以下述结构体为例:

struct S1 
{
	char  c1; 
	int   c2;
 	short c3;
};

(1)确认对齐值

        无预编译指令,指定对齐值默认位linux 32位 4字节对齐。

 (2)根据规则一排列成员

        c1:排列在结构体初始位置 0x0000。

        c2:有效对齐值为4,因此排列在4的整数倍地址上,顺序存储,c1后的地址0x0004未被占用可用。

        c3:有效对齐值为2,因此排列在2的整数倍地址上,顺序存储,c2后的地址0x0008未占用可用。

(3)规矩规则二补齐结构体

        结构体有效对齐值为其最大成员c2的自身对其值 4。目前未补齐前结构体占10个字节(c1:1,保留3,c2:4,c3:2),不是4的整数倍,因此补齐两个字节,12为4的整数倍。

 (4)计算总大小

        c1:   0x0000~0x0001    占1个字节。

        保留:0x0001~0X0004   占3个字节。

        c2:   0x0004~0x0008    占4个字节。

        c3:   0x0008~0x0010    占2个字节。

        保留:0x0010~0X0012   占2个字节。

        共计12字节。

3、结构体嵌套

        如果一个结构体B里嵌套另一个结构体A,还是以最大成员类型的字节对齐,但是结构体A存储起点为A内部最大成员整数倍的地方。(struct B里存有struct A,A里有char,int,double等成员,那A应该从8的整数倍开始存储。),结构体A中的成员的对齐规则仍满足自身的规则 。

注意:结构体A整体所占的大小为该结构体成员内部最大元素的整数倍,不足补齐。 

struct A{
	int a;
	double b;
	short c;
}A;

struct {
	char d[2];
	int e;
	double f;
	short g;
	struct A h;
    short i;
}B;

(1) 确认对齐值

 (2) 按照规则一排列结构体B中嵌套的结构体A之前的成员。

 (3)之后排列嵌套结构体A。这里要注意三点:

        1.结构体A存储起点为A内部最大成员整数倍的地方。

        2.结构体A的其他成员排列按照规则一。

        3.结构体A整体所占的大小为该结构体成员内部最大元素的整数倍,不足补齐。 

(4)继续按照规则一补足结构体B剩余部分。 按照规则二补齐剩余部分。

 编程应用

结构体字节对齐就是以空间换时间。

1、节省空间

        编程时把结构中的变量按照类型大小从小到大声明,尽量减少中间的填补空间。

2、节省时间

        以空间换取时间的效率,我们显示的进行填补空间进行对齐,比如:有一种使用空间换时间做法是显式的插入reserved成员:

struct A{
    char a;
    char reserved[3]; //保留,使用空间换时间
    int b;
}

        reserved成员对我们的程序没有什么意义,它只是起到填补空间以达到字节对齐的目的,当然即使不加这个成员通常编译器也会给我们自动填补对齐,我们自己加上它只是起到显式的提醒作用.

3、隐患

        在有字节对齐的结构体中使用指针强转取值时,容易发生越界访问的隐患。

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值