结构体内存的对齐规则(重点)

一. 结构体内存的计算方式

先给几个例子

例1:

struct s1
{
    char c1;
    int i;
    char c2;
};

例2:

struct s2
{
    int i;
    char c1;
    char c2;
};

以上两个例子的内存大小是否一样?

我们来运行一下

运行程序之后可以观察到这两个结构体内存大小竟然不一样,那我们应该如何计算结构体内存大小呢?

结构体在计算其大小的时候有一定的对其规则

结构体对齐规则:

1.结构体的第一个成员,对其到结构体在内存中存放位置的0偏移处

2.从第二个成员开始,每个成员都要对齐到一个对齐数的整数倍处

对齐数:结构体自身大小和默认对齐数的较小值

例:VS的默认对齐数为 8,linux,gcc没有对齐数,对齐数就是成员自身大小

3.结构体的总大小,必须是所以成员的对齐数中最大对齐数的整数倍

4.如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处结构体的总大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍

我们自己来算一下例1,例2

在vs环境下:

例1:

struct s1
{
    char c1;
    int i;
    char c2;
};

根据上图可以看到,该结构体浪费了六个字节

例2:

struct s2
{
    int i;
    char c1;
    char c2;
};

一般都使用struct s2这种顺序,因为例2相对例1而言节省了4个字节的空间

我们在计算结构体的大小时会遇到很多情况:

例3:

结构体嵌套该怎么计算?

struct C3
{
    double d;
    char c;
    int i;
};

struct C4
{
    char c1;
    struct C3 c3;
    double d;
};

先算出struct C3的结构体大小

根据结构体对齐规则得出struct C3的大小为:16

然后根据规则4

注:是到31,这里往下多对齐了一个

我们来运行看一下结构体大小是否为32

运行结果:

例4:

结构体中含有数组怎么计算?

struct s2
{
    char c1;
    int a[5];
    char c2;
};

计算时将int a[5]看成5个int a //对齐数为4 ,int a[5]是一个连续的空间

1 + 27 = 28 我们来看看结果对不对呢!

运行结果:

二. 为什么存在结构对齐?

大部分参考资料是这样写的:

1.平台原因(移植原因):

不是所有的硬件平台都能访问任意位置上的任意数据的;某些硬件平台只能在某些地址处取某些特定类型的数据,否则抛出硬件异常

2.性能原因

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

例:

没对齐之前:访问i的空间需要访问2次

对齐之后:访问i只需要访问一次

三.修改默认对齐数

设计结构体的时候,我们即要满足对齐,又要节省空间,如何做到:

让占用空间小的成员尽量在一起

vs环境下默认对齐数位:8

使用#pragma pack()可以调节默认对齐数

例:

#pragma pack(1) //修改默认对齐数为1
struct s1
{
    char c1;
    int i;
    char c2;
};

运行程序:

  • 24
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值