struct结构体的使用
和数组一样,struct可以保存多个成员数据,不同的是数组都是相同类型的数据,而struct可以保存不同类型的成员数据
用法:
struct Node {
int i;
char arr[3];
};
struct Node abc;
结构体变量也可以写在结构体构造时的末尾:
struct Node {
int i;
char arr[3];
}abc;
同样,也可以使用typedef对结构体进行重命名(下面代码意思就是将struct Node重命名为stu,创建结构体变量时就可以直接stu abc了):
typedef struct Node {
int i;
char arr[3];
}stu;
还有一种偏僻的写法叫做匿名结构体,就是不写结构体名,直接在结尾创建结构体变量,但是这样写的话后面就不能再创建该结构体的变量使用:
struct {
int i;
char arr[3];
}stu;
struct的内存对齐
首先看看上面创建的结构体变量的大小,int i+char arr[3]直接计算的话应该是7个字节大小,那么在结构体中也是这样吗
可以看到,结果为8,造成这种结果的原因就要谈到结构体的内存对齐规则了,首先有一个偏移量的概念,偏移量就是指离结构体起始内存位置的字节数,1、结构体的首个成员永远位于偏移量为0的位置,下面再创建比较复杂的结构体,使用offsetof宏函数观察每个成员的偏移量,该宏的头文件为stddef.h
通过运行结果和图可以清楚看到,char j到int i一共有4个字节大小,中间空了3字节的空间,这就是结构体内存对齐的第二条规则:2、从第二个成员开始,每个成员都要对齐到对齐数整数倍的位置。对齐数:默认对齐数和自身大小的较小值,vs对齐数为8。int i的对齐数就为4,char j已经占了一个字节,所以i就需要到偏移量为4的位置对齐
我们还可以看到,sizeof该结构体变量为24,图上为4+4+8+3=19,这就是第三条规则:3、结构体整体的大小为结构体成员最大对齐数的整数倍,而上图的结构体成员最大对齐数为double k的8,19补全即为24
还有一种情况就是:4、结构体内嵌套另一个结构体,这个时候嵌套的结构体对齐数为自身的最大对齐数,对齐后往后补全所占内存,最后对齐结构体和嵌套的结构体中最大对齐数的整数倍
因此,我们在设计结构体时,应该将较小的结构体成员放在一起,这样就能防止内存对齐时浪费太多空间(修改默认对齐数#pragma pack(num),num就为修改的默认对齐数)
位段
位段即为struct成员变量指定可以使用的内存大小,大小为bit:
struct num {
char i : 3;
char j : 1;
int k : 11;
};
后面给了冒号+值的都是位段,如果申请的一个内存块能放得下两个指定内存的成员变量,就会放在同一个内存块,但是如果放不下,那么该内存块剩余部分是否使用还是直接重新分配,标准比较模糊,这里不做深入探讨
union联合体
可以看到联合体union Nu num的大小为8个字节,并且联合体和所有成员都指向同一个地址,也就是说所有成员都是公用同一块空间的,所以联合体也叫共用体。当然,共用体一次也只能使用一个,否则同一个地址会产生影响,因此我们可以判断union联合体的大小就为最大的那个成员大小