C语言中结构体的对齐规则

参考博客:

结构体的内存空间分配原理

结构体在内存中的对其规则

C/C++语言中结构体的内存分配小例子

结构体对齐是为了更加快速的读取结构体中的变量。对齐之后,多余的内存空间被“填充”了,其中不放任何数据。

1、结构体的对齐规则

结构体的成员是按顺序排列在内存地址中的,根据结构体的对齐规则,结构体中的元素顺序可能会影响结构体整体占用的字节数。

规则一:结构体中的第一个成员位置在偏移量0,之后每个变量的偏移量必须是它本身字节数的整数倍。

规则二:如果结构体中嵌套结构体,那么嵌套的结构体的偏移量必须是它最大成员的字节数的整数倍。

规则三:结构体的总偏移量必须是它最大成员字节数的整数倍。

对于C++中的类也是同样的规则。

2、结构体的对齐实例

用sizeof计算各类型的字节数,得到结果如下表

char1short2
int4float4
long8double8
void*8


以下是求偏移量和长度的函数:

typedef unsigned int ui;
#define addr(x) (ui)(long)(x)
template <typename T>
void GetOffset(T t)
{
    ui startAddr = addr(&t);
    cout << "a: 0" \
        << "\tb: " << addr(&t.b)-startAddr \
        << "\tc: " << addr(&t.c)-startAddr \
        << "\td: " << addr(&t.d)-startAddr \
        << "\nlen: "<< sizeof(t) << endl;
}

(1)结构体s1

结构体s1的定义是:

struct s1{
    int a;  // 4
    short b;// 2
    long c; // 8
    float d;// 4
};

计算的结果是:

s1
a: 0	b: 4	c: 8	d: 16
len: 24

存储空间表示如下:

(2)结构体s2

结构体s2的定义是:

struct s2{
    char a; // 1
    char b; // 1
    short c;// 2
    long d; // 8
};

计算的结果是:

s2
a: 0	b: 1	c: 2	d: 8
len: 16

存储空间表示如下:

(3)类s3

类s3的定义是:

class s3{
public:
    char a;     // 1
    long b;     // 8
    short c;    // 2
    char d;     // 1
};
计算的结果是:

s3
a: 0	b: 8	c: 16	d: 18
len: 24
存储空间表示如下:

(4)类s4

类s4的定义是:

class s4{
public:
    char a;     // 1
    char b;     // 1
    short c;    // 4
    long d;     // 8
};
计算的结果是:
s4
a: 0	b: 1	c: 2	d: 8
len: 16
存储空间表示如下:

可以看出,类s3和类s4中的元素是一样的,只是顺序有些许差别,但因为对齐规则的存在,导致了两者所占用的空间完全不同。

(5)结构体s5

结构体s5的定义是:

struct s5{
    int a;      // 4
    s4 b;       // 16 max 8
    char c;     // 1
    float d;    // 4
};
这里的第二个量嵌套了类s4,根据之前的计算结果得知该类占用的空间为16字节,其中最大类型是8字节。

计算的结果是:

s5
a: 0	b: 8	c: 24	d: 28
len: 32
存储空间表示如下:

3、指定对齐字节

对齐的指令为

#pragma pack(n)

#pragma pack(push, n)

作用是比较结构体中的最大宽度和指定的数,取其中较小的那个作为对齐字节数。

在计算结构体s1空间之前分别设定对齐字节数为4和16,则计算的结果分别是:

pack(4)
a: 0	b: 4	c: 8	d: 16
len: 20

pack(16)
a: 0	b: 4	c: 8	d: 16
len: 24
当对齐数为16时,因为最大宽度是8,小于16,所以存储方式不变;当对齐数设置为4时,小于最大宽度8,因而对齐数为4,存储方式如下图所示:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值