C语言:结构体——关于内存字节对齐图文详解

前言:

我们在学到c语言内存管理的时候总是一遍惊叹,其聪明的内存管理策略,一遍抱怨其难以理解的方法,网上的资料要不讲究的太详细,要不没能讲解清楚,今天我们根据实例来学习一下基于32位操作系统的的C语言:内存字节对齐

tip:在32位编译模式下,默认以4字节对齐;在64位编译模式下,默认以8字节对齐。

目录

1. 什么是对齐?

2. 计算机为什么要对齐?

 3.我们直接上代码

案例一

 案例二

对齐规律 

名词解释:

对齐有两个规则:


1. 什么是对齐?

  现代计算机中内存空间都是按照字节(byte)划分的,从理论上讲似乎对任何类型的变量的访问可以从任何地址开始,但实际情况是在访问特定变量的时候经常在特定的内存地址访问,这就需要各类型数据按照一定的规则在空间上排列,而不是顺序地一个接一个地排放,这就是对齐。

2. 计算机为什么要对齐?

  各个硬件平台对存储空间的处理上有很大的不同。一些平台对某些特定类型的数据只能从某些特定地址开始存取,其他平台可能没有这种情况。但是如果不按照适合其平台的要求对数据存放进行对齐,会在存取效率上带来损失。

例如一个 int 类型的数据,如果地址为 8,那么很好办,对编号为 8 的内存寻址一次就可以。如果编号为 10,就比较麻烦,CPU需要先对编号为 8 的内存寻址,读取4个字节,得到该数据的前半部分,然后再对编号为 12 的内存寻址,读取4个字节,得到该数据的后半部分,再将这两部分拼接起来,才能取得数据的值。

将一个数据尽量放在一个步长之内,避免跨步长存储,这称为内存对齐。在32位编译模式下,默认以4字节对齐;在64位编译模式下,默认以8字节对齐。

 3.我们直接上代码

案例一

#include <stdio.h>

void main(){

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

    printf( "size of struct A = %d \n", sizeof(struct A) );

}

输出结果为:8字节。

我们来看图

第一步:

首先自身对齐值最大(也就是int型)是4  32位操作系统的对齐值也是4,所以有效对齐值就是4

第二步:

满足存放成员的起始地址必须是该成员有效对齐值的整数倍

a是char型数据,占用1字节内存;short型数据,占用2字节内存;int型数据,占用4字节内存。因此,结构体A的自身对齐值为4。于是,a和b要组成4个字节,以便与c的4个字节对齐。而a只有1个字节,a与b之间便空了一个字节。我们知道,结构体类型数据是按顺序存储结构一个接一个向后排列的

 案例二

#include <stdio.h>

void main(){

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

    printf( "size of struct A = %d \n", sizeof(struct A) );

}

输出结果为:12字节。

我们来看图

第一步:

自身对齐值最大(也就是int型)是4  32位操作系统的对齐值也是4,所以有效对齐值就是4

第二步:

满足存放成员的起始地址必须是该成员有效对齐值的整数倍

b是short型数据,占用2字节内存;chart型数据,占用1字节内存;int型数据,占用4字节内存。因此,结构体A的自身对齐值为4。于是,b一个数据占4字节(原本是两个字节),c一个数据占4字节,a一个数据占4字节(原本一个字节)

类比成这样子(对齐的样子)

对齐规律 

名词解释:

这里引入四个概念

数据类型自身的对齐值,

指定对齐值,

结构体或者类的自身对齐值,

数据成员、结构体和类的有效对齐值

  1)数据类型自身的对齐值:就是基本数据类型的自身对齐值,比如char类型的自身对齐值为1字节,int类型的自身对齐值为4字节。

  2)指定对齐值:预编译命令#pragma pack (value)指定的对齐值value。

  3)结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值,比如以上的struct A的对齐值为4。

  4)数据成员、结构体和类的有效对齐值:自身对齐值和指定对齐值中较小的那个值。

对齐有两个规则:


1、首先 结构体的自身对齐值操作系统的对齐值相比的那个就是有效对齐值

比如下面这个 结构体的自身对齐值是4 操作系统的对齐值也是4,所以有效对齐值就是4   

#include <stdio.h>

void main(){

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

    printf( "size of struct A = %d \n", sizeof(struct A) );

}


2、满足存放成员的起始地址必须是该成员有效对齐值的整数倍。

通俗来说就是每一个数据类型有效对齐值相比                 取大的那个值就是最后的有效对齐值

#include <stdio.h>

void main(){

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

    printf( "size of struct A = %d \n", sizeof(struct A) );

}

还是上面的代码,b为short型(1字节)和有效对齐值(4字节)相比取大的值就是4字节

  • 8
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

heart_6662

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值