结构体成员的内存分配

  • Post author:
  • Post category:其他




结构体的内存分配

举个例子就明白了,如下图,似乎除了结构体名没什么区别,内存大小和内存分布也应该没什么区别,

在这里插入图片描述

但是实际上:

 sizeof(A) = 9
 sizeof(B) = 16

导致这一差异的就是内存对齐,为什么有内存对齐,以及什么是内存对齐在这就不阐述了,可以自行度娘,反正目的是为了加快性能, 内存对齐的规则如下,也是编译器给结构体开辟内存时遵循的规则:

1、第一个成员的相对于结构体首地址的偏移(offset)为0.

2、每个成员的相对于首地址的偏移(offset)为:

对齐值与成员类型长度的较小值

的整数倍

3、没有指定对齐值的情况下,默认对齐值为结构体成员类型最长的值作为对齐值

4、结构体的总大小,为对齐值的整数倍。

这个规则就确认了结构体成员的内存分布及内存大小,上图中,结构体A指定了内存对齐为1字节对齐,那么按照规则A中各成员分布如下图:

在这里插入图片描述

B为默认对齐,显然,对齐值为类型int的长度,假设为4,内存分配如下图:

在这里插入图片描述

为什么会如此分布?我们尝试给每个成员分配内存

  • c1: 分配内存为1字节,占据索引为“0”的位置
  • i: 分配4个字节长度,但是按照规则2,距首地址要有4的整数倍偏移,所以i为起始位置为“4”,长度为4
  • c2: 分配1字节,占据索引为“8”的位置 s2: 分配2字节,依照规则2,偏移为2个倍数,起始为“10”,长度为2
  • c3:分配1个字节,占据索引为“12”的位置,按照规则4,总长度需要是4的倍数,因此还需要额外补充3个字节

因此B的总长度16,其中有部分内存是未使用的,可以说是浪费的,但是合理的

以下是一段测试验证代码:


#include <iostream>
#include <new>
#include <cstdio>
using namespace std;

#pragma pack(1)
struct A
{
public:
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
};
#pragma pack()

struct B
{
    char c1;
    int i;
    char c2;
    short s1;
    char c3;
};
void printA(A a){

    cout<<"A:"<<a.c1<<","<<a.i<<","<<a.c2<<","<<a.s1<<","<<a.c2<<","<<a.c3<<endl;
    int h1 = 0x000000ff & a.i;
    int h2 = 0x000000ff & (a.i >>8);
    int h3 = 0x000000ff & (a.i >>16);
    int h4 = 0x000000ff & (a.i >>24);
    cout<<"h1:"<<h1<<" h2:"<<h2<<" h3:"<<h3<<"  h4:"<<h4<<endl;

}

void printB(B a){

    cout<<"B:"<<a.c1<<","<<a.i<<","<<a.c2<<","<<a.s1<<","<<a.c2<<","<<a.c3<<endl;
    int h1 = 0x000000ff & a.i;
    int h2 = 0x000000ff & (a.i >>8);
    int h3 = 0x000000ff & (a.i >>16);
    int h4 = 0x000000ff & (a.i >>24);
    cout<<"h1:"<<h1<<" h2:"<<h2<<" h3:"<<h3<<"  h4:"<<h4<<endl;

}

int main(int argc, char *argv[])
{

    cout<<"sizeof(A)"<<sizeof(A)<<endl;
    cout<<"sizeof(B)"<<sizeof(B)<<endl;

    //26个字母的字符
    char buff[26] = {0};
    for(int i=0;i<26;i++)
        buff[i] = 97+i;//字符 a 的值为97

    A a = {0};
    memcpy(&a,buff,sizeof(A));
    printA(a);
    B b = {0};
    memcpy(&b,buff,sizeof(B));
    printB(b);


}

程序打印

在这里插入图片描述

打印结果和理论上是一致的(下图的内存分布)

在这里插入图片描述

假设结构体重包含结构体内存怎么分配?依然按照原则分配就是,值得一提的是,内存对齐值不是结构体的长度,而是结构体内部成员类型长度最大的值,你可以理解为对齐值对比的是基础类型的内存长度(char,short,int,long,double,float等),下图中内存对齐值不是sizeof(B),而是结构体B中的类型int的所占内存的长度值。


那么这里的B的起始位置为什么在“105”而不是在“102”?


依然对比规则,规则2规定了,每个成员的偏移量为内存对齐值的整数倍,结构体B才是是D的成员,所以B的起始位置距离D结构体的起始位置要是4的倍数,因此B的起始位置在“105”

在这里插入图片描述



版权声明:本文为dai1396734原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。