目录:
结构体
结构是一些值的集合,这些值成为成员变量。结构的每个成员可以是不同类型的变量
结构体的声明
struct s
{
char a;
int b;
}s1;
这里的a和b就是结构体的成员变量,s1就是结构体的名字。
当我们在声明结构体时,可以忽略掉结构体标签s,进行不完全声明
struct
{
char a;
int b;
}s2;
这两个一样吗?虽然它们看上去一样,但是因为标签不同,编译器会将它们当作两个完全不同的类型。
结构体的自引用
在一个结构体中我们是否可以包含一个这个结构体本身的成员变量呢?
答案是可以的,但是也是有条件的,我们只能引用这个结构体类型的指针
这里s1的写法就是不允许的,我们只能通过声明这个结构体类型的指针来实现自引用。
这种用法在我们数据结构中的链式存储结构中经常可以看到。
同时还有一个需要注意的地方,在声明结构体时,很多同学都是使用typedef来重命名结构体,但是如果结构体中存在自引用的话,我们就不能使用重命名后的名字来声明自引用,因为重命名在结构体内部成员成员变量的声明之后。
结构体的定义和初始化
了解了结构体的基本内容,下面来看看如何定义结构体变量。
我们可以在声明结构体的时候进行定义,也可以单独进行定义
这里的s1和s2就分别是这两种方法。
同时我们的初始化也遵循这个原则
同时结构体还是可以嵌套初始化的,只需要内部再加一个中括号即可,在这里就不进行演示了。
结构体传参
之前我在指针那一章中讲到过数组的传参,而结构体的传参也与它大同小异。
传参分为两种,一种传地址,一种传数值。结构体与数组不同的地方就在于它是两种都支持的,
这里的test1是传整个结构体,test2是传指针,它们两个都是可以编译通过的,但在实际应用中我们应该选择第二种,因为在传参的时候参数是需要压栈的,会有时间和空间上的开销。同时如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销也就越大,会导致性能的下降。
所以当我们在进行结构体传参的时候应该传结构体的地址
结构体还存在位段和内存对齐,因为难以理解所以我单独发了一个博客进行讲解。
结构体内存对齐,位段详解:https://blog.csdn.net/qq_35423154/article/details/103190437
枚举
枚举理解起来十分简单,就是将可能的取值一一列举出来
定义的方式
其中的day1-5是枚举类型的可能取值,也叫枚举常量
第一项为0, 每次递增一位,我们可以在定义时给其赋初值。
为什么要使用枚举呢?
- 增加代码的可读性和可维护性
- 和#define定义的标识符比较,枚举有类型检查,更加严谨
- 防止了命名污染
- 便于调试
- 使用方便,一次可定义多个变量
只能拿枚举常量给枚举变量赋值,才不会出现类型的差异
联合
联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征时这些成员公用一块空间。
声明方式
当我们想看它的大小时,发现又和之前的几种不一样了。
这是为什么呢?
- 联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小
- 当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
如;
因为联合体的成员是共用同一块空间的,所以我们可以利用这个特点,更简单的来判断机器的大小端
之前讲的方法:https://blog.csdn.net/qq_35423154/article/details/102712686