本章重点
结构体
- 结构体类型的声明
- 结构的自引用
- 结构体变量的定义和初始化
- 结构体内存对齐
- 结构体传参
- 结构体实现位段(位段的填充&可移植性)
枚举
- 枚举类型的定义
- 枚举的优点
- 枚举的使用
联合(共用体)
- 联合类型的定义
- 联合的特点
- 联合大小的计算
1.结构体
1.1 结构体类型的声明
结构的基础知识:结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量。
#include <stdio.h>
// 声明一个结构体类型,名字叫stu
// 里面的内容叫做结构体成员变量
struct stu
{
char name[20]; // 名字
int age; // 年龄
char sex[5]; // 性别
char id[20]; // 学号
}s3,s4,s5; // 分号不能少,s3,s4,s5为全局的结构体变量,与下面的声明相同
// 创建结构体变量,全局变量,在函数内部叫做局部变量
struct stu s1;
struct stu s2;
int main(){
struct stu s6; // 局部变量
return 0;
}
特殊声明:不常用
// 匿名结构体
struct
{
int a;
char b;
float c;
}x; // 通过x.的方式进行调用结构体成员变量
1.2 结构体的自引用
struct Node
{
int date;
struct Node *next;
};
1.3 结构体变量的定义和初始化
// 结构体变量重定义
typedef struct node
{
int data;
} Node;
int main()
{
struct node n1;
Node n2;
return 0;
}
struct S{
char c;
int a;
double d;
char arr[];
};
struct S s = {'A',10,3.14,"world"};
1.4 结构体传参
结构体传参,采用传地址的方式,效率更高
函数传参的时候,参数是需要压栈的,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
#include <stdio.h>
struct S
{
int a;
char c;
double d;
};
void init(struct S *temp)
{
temp->a = 100;
temp->c = 'a';
temp->d = 3.14;
}
void print1(struct S temp)
{
printf("%f\n", temp.d);
}
void print2(struct S *temp)
{
printf("%f\n", temp->d);
}
int main()
{
struct S s;
init(&s); // 给结构体传参
print1(s); // 调用结构体参数进行计算
print2(&s); // 调用结构体参数进行计算,常用方法2
return 0;
}
1.5 结构体位段
位段的声明和结构是类似的,有两个不同:
- 位段的成员必须是int、unsigned int 或 signed int,只要整型即可,char也是整型
- 位段的成员名后边有一个冒号和一个数字
位段:二进制位,位段用来节省空间
位段内存的分配:
- 位段的成员可以是int unsigned int signed int或者是char(属于整型家族)类型
- 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的‘
- 位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段
#include <stdio.h>
struct S
{
int a : 2; // 给a 2个比特位
int b : 5; // 给b 5个比特位
int c : 10;
int d : 30;
};
// 共47个bit位,换算成字节,6个字节即可满足
int main()
{
struct S s;
printf("%d\n", sizeof(s)); // 8个字节
}
2 枚举
枚举顾名思义就是列举,把可能的取值进行列举。
枚举类型的定义:
enum Color
{
RED, // 默认为0,可以赋初始值,例RED = 1
YELLOW, // 1
BLUE // 2
};
int main(){
enum Color r = RED; // 赋其他值会报错
return 0;
}
枚举的优点:可以使用#define定义常量,为什么非要使用枚举?
- 增加代码的可读性和可维护性
- 和#define定义的标识符比较,枚举有类型检查,更加严谨
- 防止命名污染(封装)
- 便于调试
- 使用方便,一次可以定义多个常量
枚举的使用:
3 联合(共用体)
- 联合类型的定义:联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
- 联合的特点:共用同一块内存空间,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
// 联合类型的声明
union un
{
char c;
int i;
};
int main()
{
union un u;
printf("%d\n", sizeof(u)); //结果为4
return 0;
}
联合大小的计算:
- 联合的大小至少是最大成员的大小
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍