前言
在C语言中,除了最常见用数据类型,字符类型(char)、整数类型(short、int、long )、实型(float、double),,,,,,最常见也是最经典的还有一种数据类型,那就是结构体。
那么结构体的大小该怎去计算呢?首先先得知道不同数据类型的大小
一、数据类型有哪些?
char //字符数据类型
short //短整型
int //整形
long //长整型
long long //更长的整形
float //单精度浮点数
double //双精度浮点数
各个数据类型本身大小如下
二、结构体常规认知
1.什么是结构体
定义:结构体是一系列数据的集合,这些数据可能描述了一个物体,也可能是对一个问题的抽象。举个栗子,简单的说,对于人,人有名字,性别,年龄,身高,体重等个人信息,那么,我们在定义这种个体的时候,就不能说它能用一个字符或整型变量来定义。 这时候,就需要结构体闪亮登场了。
typedef struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}Stu;//分号不能丢
2.什么情况下会用到结构体?
- a、一般当内置内存无法满足用户需求,没有合适类型对应对象时,需要封装特定的类型
- b、当函数有多个参数时,返回值过多,需要封装特定类型,将参数打包返回。
- c、无法满足定义变量的需求时,放开了自定义权限,于是 struct 关键字就应运而生了。
3.结构体内存对齐
我们先看几个用例
struct S1
{
char c1; //4
int i; //4
char c2;//4
};
是不是觉得结构体的大小就是 1+4+1=6呢? 那就错了 看看下面的正确答案
答案是12 那么为什么呢? 这就牵扯到了结构体内存对齐。
怎样对齐呢?
. 第一个成员在与结构体变量偏移量为0的地址处。
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。
VS中默认的值为8
3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整 体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
上面说的是什么意思呢 我们再看上面的例子
char 1+int 4=5 因为对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值 这个较小值就是int 4 也就是对齐数 要是他的整数倍 只需加一个 3 所以char 补三个空间 为8个 下面的一样 补3个 所以最后就是 4+4+4=12
这里给三个判断原则 根据这个就简单了许多
原则1:结构体中元素是按照定义顺序一个一个放到内存中去的,但并不是
紧密排列的。从结构体存储的首地址开始,每一个元素放置到内存中时,它都
会认为内存是以它自己的大小来划分的,因此元素放置的位置一定会在自己宽度的整数倍上开始(以结构体变量首地址为0计算)。原则2:结构体作为成员:如果一个结构里有某些结构体成员,则结构体成员要从其内部最大元素大小的整数倍地址开始存储。
原则3:结构体的总大小,必须是其内部最大成员的整数倍,不足的要补齐。
我们再看几个实例
1.
这个大小为什么是8呢?
首先结构体中元素是按照定义顺序一个一个放到内存中去的 char 一个字节+ char 一个字节 为2个字节 又说结构体的总大小,必须是其内部最大成员的整数倍 最大内部成员为int4 所以再补2个空间即刻
得2+4+2=8 是4的倍数。
2.
答案为16
double已经最大8了 不需要补齐了 就看 下面的 char int 根据 对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。 这个较小对齐值为4 所以char补三个 得4 最后8+4+4=16是最大内部成员8的整数倍
3.
这个稍有难度
首先 struct S3的大小是16 这里的对齐数只能是vs默认的最大对齐数为8 所以char补7 double本身就是8 不用补 所以大小是 8+16+8=32 是最大内部成员16的整数倍
总结
若牵扯到结构体内存对齐 首先看结构体类型的顺序,然后找出里面成员类型最大的, 然后根据原则补齐,最后判断是不是内部最大成员类型的整数倍。
如有错误,还望大家指正,感谢您的阅读!!!