结构体对齐

什么是对齐

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

为什么要对齐

底层逻辑都是需要数据对齐,这是由电脑cpu,内存等基础架构决定的。其一是如果CPU读取未对齐的数据,本来一次可以读取完的数据,我们要读两次,拖慢程序效率其二是,有些架构的CPU如果读取没有对齐的数据,会抛出异常,程序的兼容性很差。
我们之前讲了很多关于内存的知识
程序员眼中的内存:

结构体对齐

CPU眼中的内存:

结构体对齐

比如我们要读取32位系统 的一个整型 也就是4字节 如果我们从地址1开始读 则需要先读取0-3 然后再读取4-7 就和排队一样 前面是整齐的后面就整齐 前面站的错开了 后面就跟着都错开了 数起来还不好数;说白了,一个正确的字节对齐方式,就是为了让CPU在最短的时间内读取完变量,同时还让整体的结构存储空间最小。
详细我们下面再介绍

对齐规则

1)结构体总长度;
2)结构体内各数据成员的内存对齐,即该数据成员相对结构体的起始位置;
细分步骤:
1.确定结构体第一个结构体变量位于结构体0偏移的位置
2.对齐其他成员变量通过对齐数 对齐数就是编译器默认的一个对齐数与该结构体中的成员变量大小中的较小值
3.结构图总大小是最大对齐数的整数倍(成员、结构体都有自己的对齐数)
虽然到目前为止你也没看懂我写的是什么,但下面我将详细介绍对齐数,才通过规则和例子帮你理解。

对齐数

首先明确四个概念
成员对齐值:基本数据类型的对齐数
结构体对齐值:数据成员对齐值最大的值
指定对齐值:系统默认或者我们使用 #prama pack(value) 指定对齐值 value
有效对齐值:数据成员 结构体 和指定对齐值中较小的一个

#prama pack(4)
struct Game_person
{
	char b;
	int a;
	short c;
};
C++

我这里因为大家系统和CPU都不一样,我就指定指定对齐数为4;再来看各成员的对齐数
char b //对齐数 = 1 有效对齐数min(1,4);
int a //对齐数 = 4 有效对齐数min(4,4);
short c //对齐数 = 2 有效对齐数min(2,4);
然后我们再看结构体的对齐数 因为成员基本类型对齐数 最大是4 所以该结构体的对齐值是4 min(4,4) 所以该结构体的有效对齐值是4
那我们现在就把这个结构体对齐

#include<stdio.h>
#prama pack(4)
struct Game_person
{
	char b;  //对齐数 = 1  有效对齐数min(1,4);
	int a;     //对齐数 = 4 有效对齐数min(4,4);
	short c;  //对齐数 = 2 有效对齐数min(2,4);
};
C++

我们前面说的规则可能很晦涩,如果没有#prama pack(4)一般来来说对齐规则就是结构成员的对齐值的最大值 但是既然有了#prama pack(4)我们就以指定对齐值为对齐规则。
CPU如果读取内存的话会每次读4个字节,char虽然是1个字节,但CPU会读4个字节 。这就是我们之前说的如果我们紧贴着char后面存放intCPU要读取两次如果一次读四个字节是不是char 和 int都可以一次性读完。

struct weapon
{
	char b;  //对齐数 = 1  有效对齐数min(1,4);
	short a;     //对齐数 = 5 有效对齐数min(2,4);
	int c[2];  //对齐数 = 4 有效对齐数min(4,4);
}weapon1;
C++

现在我们用CPU的角度看一下如何读取这个结构体;

结构体对齐

如图 那么它的大小=2+2+4+4 = 12 12%4 = 0所以是符合规则的

结构体对齐

内存对齐的计算方法

  1. 保证每一个数据满足:不同类型数据都满足:当前数据存储的首地址 % 数据有效对齐值 = 0;
  2. 补齐末尾的空间,保证长度对齐,即总长度 % 实际对齐长度 = 0;
    总长度就是我们结构体对齐之后的长度 实际对齐长度就是结构体的有效对齐值

选择最好的对齐字节数值

如何选择最好的对齐数值
设置不同的字节对齐方式对于数据的存储空间来说有不同的影响,在和变量自身对齐值为整数数关系下,选择变量有效对齐值中位数附近的数值效果最好。

#include<stdio.h>
#prama pack(4)
struct Game_person
{
	char b;  //对齐数 = 1  有效对齐数min(1,4);
	int a;     //对齐数 = 4 有效对齐数min(4,4);
	short c;  //对齐数 = 2 有效对齐数min(2,4);
};
C++

变量有效对齐数 1 4 2 所以中位数是2 然后就可以将指定对齐值修改为2

#include<stdio.h>
#pragma pack(2)
struct Game_person
{
	char b;  //对齐数 = 1  有效对齐数min(1,2);
	int a;     //对齐数 = 4 有效对齐数min(4,2);
	short c;  //对齐数 = 2 有效对齐数min(2,2);
}user1;
C++

我这里直接给出答案了 感兴趣的自己算着对一下
8%2 = 0 大小 = 8
运行结果:

结构体对齐

C语言

C语言数据结构_链表

2024-11-14 14:21:08

C语言

链表的实现

2024-11-14 14:52:11

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索

Powered by atecplugins.com