最近又捡起了C语言,遇到了大量对结构体操作的业务,在操作期间,发现对结构体在内存中的分配仍然存有一定的疑问。,经过学习,特把有关结构体内存分配的相关知识记录下来。
内存对齐:要了解结构体的内存分配,首先需要了解内存对齐的概念。之所以会有内存对齐的概念,是因为,在操作系统中,数据的存放时按照字节存放的,而结构体又不像数组,结构体中可以存放不同类型的数据,它的大小也不是简单的各个数据成员大小之和,限于读取内存的要求,而是每个成员在内存中的存储都要按照一定偏移量来存储,根据类型的不同,每个成员都要按照一定的对齐数进行对齐存储,最后整个结构体的大小也要按照一定的对齐数进行对齐。关于具体的概念以及为什么要采用内存对齐的方式可以参考博文:https://blog.csdn.net/Misszhoudandan/article/details/81570548。
下面就结合具体的例子来描述结构体的内存空间是怎么分配的:
1、请看下面的结构体:
struct MsgTest
{
char a;
int b;
};
MsgTest占多少个字节呢?刚开始我以为是5字节(char 1字节+int 4字节),但实际上是8字节,请看下图:
由上图可以看出,char类型的元素a的起始地址为0x43fd50,而int型元素b的起始地址为0x43fd54,也就是说,系统为元素a总共分配了4个字节的内存(虽然a本身只占用了一个字节长度的内存),剩下的3字节长度的内存就是基于内存对齐的概念进行填充的,不计入操作。
2、接下来看如下的结构体:
struct MsgTest
{
char a;
char b;
int c;
};
按照上节讲述的原则,那这个结构体所占的内存应该是12字节,但实际上他占了多少个字节呢?请看下图:
这个结构体也是占了8字节。为什么会这样呢,那是因为基于内存对齐的概念,每一个元素应该是按照4字节的标准进行补齐,但是元素a和元素b各占1字节,所以还剩下2字节需要补齐,右上图也可以看出,元素a和元素b的内存只相差了一个字节。实际上,在该结构体中即使是如下样式:
struct MsgTest
{
char a;
char b;
char c;
char d;
int e;
};
它所占的内存仍然是8个字节:
3、下面是一些其他格式的结构体:
1):
2):
在该结构体中,a占了4字节,b占了40字节(16进制为28),c占了4字节,d占了8字节,e占了8字节。
3):
可以看一下如下的题目,各位可以先算一下占多少个字节:
需要注意的是,对char*类型的元素,在内存中存放的其实是它的地址(占4字节),_int64类型的占8字节,unsigned其实是unsigned int的简写,也占了4字节。
参看答案如下所示: