目录
一.结构体
1.1什么是结构体?
1.2结构的声明
1.3特殊声明
1.4结构的自引用
1.5 结构体变量的定义和初始化
1.6 结构体内存对齐
1.7修改默认对齐数
二.联合体
2.1联合类型的定义
2.2联合的特点
2.3联合大小的计算
一.结构体
1.1什么是结构体?
结构体(struct)是一种自定义的数据类型,在其中可以包含多个不同类型的变量。结构体通常用于表示一个实体,例如一个人或一个汽车,在其中可以包含姓名、年龄、性别、品牌、颜色等属性。结构体可以通过定义变量来创建实例,并通过使用 "." 运算符来访问其中的属性。结构体在编程中经常被用来组织复杂的数据,便于处理和管理。
结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量。
1.2结构的声明
struct tag
{
member-list;
}variable-list;
例如描述一个学生:
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
}; //分号不能丢
1.3特殊声明
//匿名结构体类型
struct
{
int a;
char b;
float c;
}x;
struct
{
int a;
char b;
float c;
}a[20], *p;
- 上面的两个结构在声明的时候省略掉了结构体标签 tag
- 这种声明方法适用于在之后的代码中这个结构体我们只使用一次,不会重复一直使用。
1.4结构的自引用
错误的自引用方式:
struct Node
{
int data;
struct Node next;
};//想一想这种结构体使用自身的情况是否可行呢?
在结构体中加入该类型结构体作为成员将会使得结构体无限套娃循环,无法确定结构体的大小,因此这种做法是错误的。
正确的自引用方式:
struct Node
{
int data;
struct Node* next;
};
1.5 结构体变量的定义和初始化
struct Point
{
int x;
int y;
}p1; //声明类型的同时定义变量p1
struct Point p2; //定义结构体变量p2
//初始化:定义变量的同时赋初值。
struct Point p3 = {x, y};
struct Stu //类型声明
{
char name[15];//名字
int age; //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
int data;
struct Point p;
struct Node* next;
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化
1.6 结构体内存对齐
掌握理解了结构体内存对齐我们才能够学会正确计算结构体的大小
首先得掌握结构体的对齐规则:
- 1. 第一个成员在与结构体变量偏移量为0的地址处。
- 2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值。(VS中默认的值为8)
- 3. 结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
- 4. 如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
例子:注意:该题的默认对齐数是4
画图分析可知:对于结构体A来说从上到下每个结构体成员的对齐数最后得出是4 2 4 1,并且结构体大小应该为最大对齐数的整数倍。也就是4 2 4 1中最大数字 4的整数倍,由此我们可以得出sizeof(A)的大小是16,同理分析下直到sizeof(B)的大小是12
1.7修改默认对齐数
使用 #pragma 这个预处理指令,可以改变我们的默认对齐数
#include <stdio.h>
#pragma pack(8)//设置默认对齐数为8
struct S1
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
#pragma pack(1)//设置默认对齐数为1
struct S2
{
char c1;
int i;
char c2;
};
#pragma pack()//取消设置的默认对齐数,还原为默认
好处是:结构在对齐方式不合适的时候,我么可以自己更改默认对齐数
二.联合体
2.1联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)
//联合类型的声明
union Un
{
char c;
int i;
};
//联合变量的定义
union Un un;
2.2联合的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联
合至少得有能力保存最大的那个成员)
union Un
{
int i;
char c;
};
union Un un;
// 看输出结果观察出什么?
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
可以看出联合体共用同一块内存空间。
2.3联合大小的计算
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
分析知:
联合体 Un1 中char数组中计算对齐数按照元素来计算对齐数为1,int类型对齐数为4char数组中成员大小为5个字节,int变量为4个字节,但是5不满足为4的倍数因此联合体大小应该为8。
同理分析知Un2大小为16.
感谢大家的支持!