欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

结构体内存对齐

程序员文章站 2022-07-13 23:18:31
...

一、内存对齐的原因
1、为了提高程序的性能,数据结构应该尽可能的在自然边界上对齐。原因是为了访问未对齐的内存,处理器需要进行两次访问而访问对齐的内存只需要一次就够了。这样的方式称为“用空间来换取时间”,在对时间复杂度有要求的问题会采用这样的方法。
2、内存对齐可以增加程序的可移植性,因为不是所有的平台都能随意的访问内存。有些平台只能在特定的地址处取内存。
结构体内存对齐
栗子:

#include <iostream>
using namespace std;

struct X
{
     char a;
     int b;
     double c;
}S1;

 void main()
{
     cout << sizeof(S1) << endl;
     cout << sizeof(S1.a) << endl;
     cout << sizeof(S1.b) << endl;
     cout << sizeof(S1.c) << endl;
}

运行结果为:
结构体内存对齐
这就是结构体内存对齐的一个很典型的栗子
二、结构体内存对齐的概念
对齐原则:数据存放的起始位置是自身大小的整数倍处。
默认对齐数:在vs下内存默认对齐是8,linux是4。可以通过#program pack来修改默认对齐数。
偏移:相对与起始位置的位置。偏移的是数据类型的整数倍处。
对齐数:变量自身的大小和和默认对齐数的最小值。假设默认对齐数是8,int类型的对齐数是4,那么就会取int类型的默认对齐数。

三、结构体内存对齐的规则
1、结构或联合的数据成员,第一个成员放到0偏移的地方,以后每个成员都放到自身对齐数的整数倍偏移处。
2、结构体的大小必须是最大对齐数的整数倍。
举个栗子:

struct X
{
char a;
double b;
int c;
}s2;
这个栗子是将上面那个栗子的double变量和int型的变量互换了一下位置,但是这个sizeof(s2)却是24,这个就是第二原则的具体情况。我们分析的长度是8 + 8 +4 = 20。但是,结果却是24。因为20不是8的整数倍,所以要把它增容到8的整数倍。
结构体内存对齐
下个栗子

struct X
{
    int e;
    double a;
    char b;
    int c;
    char d;
}s3;

结构体内存对齐
前面介绍的都是单一的结构体,但是如果结构体里面嵌套一个结构体会怎么样呢?那么就看下一个栗子吧。(今天栗子管够,希望大家能吃好)

struct X
{
    char a;
    int b;
    double c;
};

struct Y
{
    char a;
    X b;
};

经过测试,可知道sizeof(X)为16,sizeof(Y)为24.即Y的长度存放的第二个元素b时的初始位置是在double型的长度的8的整数倍处,而非16的整数倍处,即系统为b分配的存储空间是8~23个字节。
如果将Y的两个元素char型的a和X型的调换顺序,则系统为b分配的存储位置是0~15个字符,为a分配的是第16个字符。17不是double的整数倍,所以要是8的倍数。就是24。

总结:
结构体所占的空间与其内部元素的类型有关,也与它们定义的顺序也是有关的。但是,只要遵守结构体对齐的规则,这也是很简单的。