C语言中结构体内存分配问题解析。

如果用sizeof关键字来求这些值的话,一般会得到上面的这些值,但是结果还和编译器有关,所以如果碰到结果不是上面的值也不要奇怪。

2. 下面我们再回到刚才讲的题目中来,如果你在VS中运行,发现上面你的结果是40,但是为什么是40呢?这里先给出一个简单的,直观的解释,其实这种解释并不是本质上的原因,只是为了方便解决问题,其实本质的原因是 编译器处理时的内存对齐机制, 我们后面会进一步谈到。

编译器在为结构体分配内存时,是按照这个结构体中占用内存字节数最大的那个变量的字节数来依次分配的,然后在这块内存中按照结构体变量中的声明顺序来依次分配空间,如果发现当前的空间不足以分配给新的变量,那么会申请新的依旧是这个数量级的内存来进行分配,而之前的会被默认的填充。我们先不解释编译器为什么要这么来做,根据上面的分析,先来看一下刚才那个题目是怎么分配内存的:

double d;是所有这些里面占有内存字节数最大的,是8;所以编译器先分配一个8B的空间。

a占用(4B) + b占用(1B) 还剩3B不够分配给c,所以剩下的3B不做分配,空闲(3B),

再申请8B,c占用(4) + 空闲(4)

再申请8B,d占用(8)

在申请8B, pa(4) + pc(4)

在申请8B, e(2) + 空闲(6)

所以我们可以看到,总共申请了5次, 8B的空间。

为了加深理解,我们将刚才函数中结构体声明变量的顺序换了一下,如下所示:

void print_struct_sizeof(){ struct A_{int c;  float b;char a;short e;double d;int *pa;char *pc;}A;cout << "The size of the struct is: " << sizeof(A)<< endl;}此时,输出的是32,大家可以自己计算一下。

3. 下面我们继续深入的学习,编译器为什么要这么做,以及究竟是怎么做的。

下面我们来看一个例子加深理解:

struct MyStruct { char dda;//偏移量为0,满足对齐方式,dda占用1个字节; double dda1;//下一个可用的地址的偏移量为1,不是sizeof(double)=8的倍数,需要补足7个字节才能使偏移量变为8,因此VC自动填充7个字节,dda1存放在偏移量为8 int type;//下一个可用的地址的偏移量为16,是sizeof(int)=4的倍 数,满足int的对齐方式,type存 放在偏移量为16的地址上,,它占用4个字节。 };

所有成员变量都分配了空间,空间总的大小为1+7+8+4=20,但总大小不是结构的节边界数(即结构中占用最大空间的类型所占用的字节数sizeof(double)=8)的倍数,所以需要填充4个字节,以满足结构的大小为sizeof(double)=8的倍数。当然,编译器也提供给我们自己的方法来进行字节的对齐,通过使用#pragma pack(n)来设定变量以n字节对齐方式。如果以n字节为对齐方式会有出现两种情况:

第一、如果n大于等于该变量所占用的字节数,那么偏移量就使用默认的对齐方式即sizeof()的整数倍。

第二、如果n小于该变量的类型所占用的字节数,那么偏移量为n的倍数,不用满足默认的对齐方式。

结构的总大小也有个约束条件,分下面两种情况:如果n大于所有成员变量类型所占用的字节数,那么结构的总大小必须为占用空间最大的变量占用的空间数的倍数; 否则必须为n的倍数。

下面举例说明其用法。

耿耿于怀着过去和忐忑不安着未来的人,也常常挥霍无度着现在。

C语言中结构体内存分配问题解析。

相关文章:

你感兴趣的文章:

标签云: