1.结构体
1.1结构的基础知识
结构是一些值的集合,值的类型是可以不同的,这些值被称为成员变量。
1.2 结构体的声明
struct str // str 为结构体标签
{
member - list; // 结构体成员列表
}variable - list; // 结构体变量列表
例如描述一本书
struct book //描述一本书 ,书名,价格
{
char name[30]; // 书名
double price; // 价格
}s1,s2; // 俩个结构体变量,s1,s2, 分号不可以省略
1.3 结构体的特殊声明
在声明结构体的时候可以不完全声明。即 ——匿名结构体类型
例如:
struct // 省略了结构体标签 (tag)
{
int i;
char j;
}a = { 5,'p'};
省略了结构体标签代码并不会出错,但是有几个我们需要注意的点。
1. 匿名结构体的变量创建和初始化必须和结构体的声明同时完成,在主函数中无法完成创建匿名结构体变量和初始化。
struct
{
char a;
int b;
}s1;
struct
{
char a;
int b;
}*ps;
int main()
{
ps = &s1;
}
即使当俩个结构体的成员变量相同时,编辑器也会默认俩个匿名结构体为不同类型,上述代码:ps = &s1 会报警告。
1.4 结构体的自引用
在结构体中,包含一个成员为结构体本身,这是否可行,又该如何实现。
struct exa
{
char a;
int b;
struct exa s2;
}s1;
程序会报错,无法运行。这种直接的嵌套显然行不通。我们可以尝试用指针来解决。
struct exa
{
char a;
int b;
struct exa *s2;
}s1;
这样的一个自引用结构体才是正确的。
1.5 typedef 重命名结构体
我们看一个例子
typedef struct
{
char f;
int i;
}node; // typedef 重命名结构体 为 node
int main()
{
// struct node s1 = { 'd' ,2 }
node s1 = { 'd',2 }; //相对于普通的结构体,在创建变量时简化了一些。
}
typedef 重命名结构体后,我们再创建结构体变量时需省略 struct
但是typedef 重命名一个自引用结构体时,应该怎么实现呢。
typedef struct
{
char f;
int i;
node* exa;
}node;
这样的代码,我们在运行时会报错。
typedef struct
{
char f;
int i;
struct node* exa;
}node;
这是正确的。
typedef 重命名的 自引用结构体,结构体中被引用的结构体 ,struct 不可省略,不可直接使用重命名后的结构体名称,必须加上 srtuct
1.6 结构体变量的定义和初始化
很简单,我们看一些例子就可以掌握。
struct score
{
int a;
int b;
}s1; // 声明结构体,同时创建变量 s1
struct score
{
int a;
int b;
}s2 = { 2,4 }; // 声明结构体,同时创建变量 s2 并初始化
struct score s3; // 定义结构体变量 s3
struct score s4 = { 1,2 }; // 定义结构体变量s4 并初始化
struct score1
{
int a;
int n;
struct score* node;
}n1 = {2,4,NULL}; //自引用结构体初始化
struct score1 n2 = {2,5,NULL} // 定义n2 并初始化
1.7 结构体传参
函数在传参的时候,需要压栈,会有时间和空间的系统消耗
如果传递的结构体对象过于大,参数压栈的系统开销比较大,会导致性能下降。
所以我们结构体传参的时候尽量传地址。
1.8 结构体内存对齐,位段
篇幅较大,我选择再写一篇。
(10条消息) 结构体内存大小计算,位段分析_杨斯文。的博客-CSDN博客
2. 枚举
2.1 枚举类型的定义
enum score //成绩
{
A,
B,
C,
D,
E
};
enum sex // 性别
{
male,
female
};
以上定义的enum score, enum sex 都是枚举类型。
{ } 中的内容 是 枚举内容的可能取值,也叫枚举常量。
枚举常量是有值的,默认为0开始,依次递增1,我们在定义的时候也可以赋值。
enum sex // 性别
{
male = 1,
female = 0
};
2.2枚举的优点
1. 增加代码的可读性和维护性
2. 和#define 定义的标识符相比,枚举有类型检查,更严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 便于使用,一次定义多个常量
2.3 枚举的使用
enum score //成绩
{
A,
B,
C,
D,
E
};
enum score stu1 = A;
只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
3. 联合(共用体)
3.1联合类型的定义
联合是一种特殊的自定义类型
这种自定义的变量也包含一系列的成员,特征是这些成员公用同一块空间
比较简单,直接用代码展示联合类型的使用
union un // 联合类型的声明
{
char c;
int i;
};
union un s1; // 定义联合变量
3.2联合的特点
1.联合的成员是公用一块内存空间的,一个联合变量的大小,至少是最大成员的大小。
2. 联合成员的起始地址都是一样的。
以上面的代码为例子
它在内存中的分布
此时这个联合变量的大小为 4 个字节。
我们可以用联合的知识来判断当前机器是大端还是小端存储
union un
{
char c ;
int i;
};
int main()
{
union un s1;
s1.i = 1;
printf("%d", s1.c);
}
数据的低位存在低地址处,小端存储。
3.3 联合大小的计算
联合的大小至少是最大成员成员变量的大小。
当最大成员大小不是最大对齐数整数倍的时候,要对齐到最大对起数的整数倍。
用一个例子来说明
union un
{
char arr[7] ;
int i;
};
union un s1;
int main()
{
printf("%d", sizeof(union un));
}
char arr 虽然是数组,但是最大对齐数还是1,int i 最大对齐数为 4,
最大成员的大小为 arr数组 ,为7, 但7 不是最大对齐数的倍数,所以需要对齐到最大对齐数的整数倍,所以这个联合的大小为 8 个字节。
本文结束,感谢观看!