结构体内存对齐详解

今天分享一道经典面试题,就是结构体是如何对齐的,以及结构体占几个字节

我们先来看一个例子

 typedef struct Test{
        char a;
        int b;
        char c;
 }Test_t;

大家猜猜这个结构体Test_t的内存是多少?
肯定有人说是6,两个char类型分别为1字节,int类型4字节,加起来正好是6
但是,结果是这样吗,我们来运行一下,结果为12
这是为什么呢?

这就是内存对齐导致的
什么是结构体内存对齐:
结构体不像数组,结构体中可以存放不同类型的数据,它的大小也不是简单的各个数据成员大小之和,限于读取内存的要求,而是每个成员在内存中的存储都要按照一定偏移量来存储,根据类型的不同,每个成员都要按照一定的对齐数进行对齐存储,最后整个结构体的大小也要按照一定的对齐数进行对齐。

结构体的对齐原则
1.第一个成员的首地址为0
2.其他结构体成员要对齐到某个数字(对齐数)的最小整数倍的地址处;
    对齐数=编译器默认的一个对齐数 与 该成员大小的较小值
    32位linux中默认为4
    64位linux中默认为8
3.结构体的总大小,为其成员中所含最大类型的整数倍

结构体的对齐步骤:
1.结构体各成员对齐
2.结构体总体对齐

怎样计算结构体的大小
实例解析:
例一:此代码在64位linux下编写

typedef struct Test1{
        char a;
        int b;
        short c;
}Test_t1;
int main(){
    printf("%ld\n",sizeof(Test_t1));
    return 0;
}

打印结果为12,让我们分析一下为什么结果为12
我们来看看上面所提到的结构体内存对齐规则:

a是char类型,占一个字节,第一个数据成员,放在结构体变量偏移量为0 的地址处
b是int类型,占4个字节,b的有效对齐值为4,对齐到4的整数倍地址,即地址偏移量为4处,在内存中存放的位置为4,5,6,7
c是short类型,占2个字节,b的有效对齐值为2.对齐到2的整数倍地址,即地址偏移量为8处.在内存中存放的位置为8,9
结构体整体的对齐数为所有成员的对齐数中最大的一个,对齐数为4
结构体整体大小,按照上面数据占据空间大小,计算的结构体大小10字节。
按照对齐规则,应该对齐到4的倍数,实际大小为12字节

 例二:

typedef struct Test2{
        char a;
        short c;
        int b;
}Test_t2;

int main(){
    printf("%ld\n",sizeof(Test_t2));
    return 0;
}

结构体Test_t1与结构体Test_t2的区别仅仅只是调换了一下各成员间的顺序,那它所占的内存还是刚才的值吗?
打印结果为8,让我们分析一下为什么是8

a是char类型,占一个字节,第一个数据成员,放在结构体变量偏移量为0 的地址处
c是short类型,占2个字节,b的有效对齐值为2,依次查看2的整数倍地址是否可以存放两个字节,将占有俩个字节的b存放在地址偏移量为2和3处
b是int类型,占4个字节,c的有效对齐值为4,对齐到4的整数倍地址,即地址偏移量为4处,在内存中存放的位置为4,5,6,7
结构体整体的对齐数为所有成员的对齐数中最大的一个,对齐数为4
结构体整体大小,按照上面数据占据空间大小,计算的结构体大小8字节。
按照对齐规则,应该对齐到4的倍数,实际大小为8字节

 我们可以看到,以上两个结构体成员变量一模一样,可是当我们按照内存对齐规则来计算两个结构体的大小的时候,会发现两个结构体的大小不一样
可以见得,结构体成员变量的顺序不同,可能会造成内存不必要的损失。将占用空间小的成员尽量集中在一起,可以有效地避免内存不必要的浪费。

此时,关于结构体的大小,我们应该清楚了不少,接下来,我们继续来看道例题:

struct S1{
    double d;
    char c;
    int i;
};
int main(){
    printf("%d\n", sizeof(struct S1));  //16
    return 0;
 }

它的结果是多少呢?16
解析:
        double类型占8个字节
        char占了下一个字节
        int的对齐数为4,所以空3个字节从12开始
        这个结构体的最大对齐数为8
        所以该结构体占2*8 = 16个字节

为什么要使用内存对齐:
平台移植性好:不是所有的硬件平台都能访问任意地址上的数据;某些硬件平台只能在某些地址访问某些特定类型的数据,否则抛出硬件异常,及遇到未对齐的边界直接就不进行读取数据了。
CPU处理效率高:为了访问未对齐的内存,处理器 需要作两次内存访问;而对齐的内存访问仅需要一次访问。


结构体内存对齐是拿空间换取时间的做法,提高效率
关于结构体内存的讲解到此为止

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值