• 【重要】C语言进阶 -- 自定义类型:结构体、枚举、联合


    本章重点

    结构体

    1. 结构体类型的声明
    2. 结构的自引用
    3. 结构体变量的定义和初始化
    4. 结构体内存对齐
    5. 结构体传参
    6. 结构体实现位段(位段的填充&可移植性)

    枚举

    1. 枚举类型的定义
    2. 枚举的优点
    3. 枚举的使用

    联合(共用体)

    1. 联合类型的定义
    2. 联合的特点
    3. 联合大小的计算

    1.结构体

    1.1 结构体类型的声明

    结构的基础知识:结构是一些值的集合,这些值称为成员变量,结构的每个成员可以是不同类型的变量

    1. #include
    2. // 声明一个结构体类型,名字叫stu
    3. // 里面的内容叫做结构体成员变量
    4. struct stu
    5. {
    6. char name[20]; // 名字
    7. int age; // 年龄
    8. char sex[5]; // 性别
    9. char id[20]; // 学号
    10. }s3,s4,s5; // 分号不能少,s3,s4,s5为全局的结构体变量,与下面的声明相同
    11. // 创建结构体变量,全局变量,在函数内部叫做局部变量
    12. struct stu s1;
    13. struct stu s2;
    14. int main(){
    15. struct stu s6; // 局部变量
    16. return 0;
    17. }

    特殊声明:不常用

    1. // 匿名结构体
    2. struct
    3. {
    4. int a;
    5. char b;
    6. float c;
    7. }x; // 通过x.的方式进行调用结构体成员变量

    1.2 结构体的自引用

    1. struct Node
    2. {
    3. int date;
    4. struct Node *next;
    5. };

    1.3 结构体变量的定义和初始化

    1. // 结构体变量重定义
    2. typedef struct node
    3. {
    4. int data;
    5. } Node;
    6. int main()
    7. {
    8. struct node n1;
    9. Node n2;
    10. return 0;
    11. }
    1. struct S{
    2. char c;
    3. int a;
    4. double d;
    5. char arr[];
    6. };
    7. struct S s = {'A',10,3.14,"world"};

    1.4 结构体传参

    结构体传参,采用传地址的方式,效率更高

    函数传参的时候,参数是需要压栈的,会有时间和空间上的系统开销。如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。

    1. #include
    2. struct S
    3. {
    4. int a;
    5. char c;
    6. double d;
    7. };
    8. void init(struct S *temp)
    9. {
    10. temp->a = 100;
    11. temp->c = 'a';
    12. temp->d = 3.14;
    13. }
    14. void print1(struct S temp)
    15. {
    16. printf("%f\n", temp.d);
    17. }
    18. void print2(struct S *temp)
    19. {
    20. printf("%f\n", temp->d);
    21. }
    22. int main()
    23. {
    24. struct S s;
    25. init(&s); // 给结构体传参
    26. print1(s); // 调用结构体参数进行计算
    27. print2(&s); // 调用结构体参数进行计算,常用方法2
    28. return 0;
    29. }

    1.5 结构体位段

    位段的声明和结构是类似的,有两个不同:

    1. 位段的成员必须是int、unsigned int 或 signed int,只要整型即可,char也是整型
    2. 位段的成员名后边有一个冒号和一个数字

    位段:二进制位,位段用来节省空间

    位段内存的分配:

    1. 位段的成员可以是int unsigned        int signed        int或者是char(属于整型家族)类型
    2. 位段的空间上是按照需要以4个字节(int)或者1个字节(char)的方式来开辟的‘
    3. 位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段
    1. #include
    2. struct S
    3. {
    4. int a : 2; // 给a 2个比特位
    5. int b : 5; // 给b 5个比特位
    6. int c : 10;
    7. int d : 30;
    8. };
    9. // 共47个bit位,换算成字节,6个字节即可满足
    10. int main()
    11. {
    12. struct S s;
    13. printf("%d\n", sizeof(s)); // 8个字节
    14. }

    2 枚举

    枚举顾名思义就是列举,把可能的取值进行列举。

    枚举类型的定义:

    1. enum Color
    2. {
    3. RED, // 默认为0,可以赋初始值,例RED = 1
    4. YELLOW, // 1
    5. BLUE // 2
    6. };
    7. int main(){
    8. enum Color r = RED; // 赋其他值会报错
    9. return 0;
    10. }

    枚举的优点:可以使用#define定义常量,为什么非要使用枚举?

    1. 增加代码的可读性和可维护性
    2. 和#define定义的标识符比较,枚举有类型检查,更加严谨
    3. 防止命名污染(封装)
    4. 便于调试
    5. 使用方便,一次可以定义多个常量

    枚举的使用:

    3 联合(共用体)

    • 联合类型的定义:联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。
    • 联合的特点:共用同一块内存空间,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
    1. // 联合类型的声明
    2. union un
    3. {
    4. char c;
    5. int i;
    6. };
    7. int main()
    8. {
    9. union un u;
    10. printf("%d\n", sizeof(u)); //结果为4
    11. return 0;
    12. }

    联合大小的计算:

    • 联合的大小至少是最大成员的大小
    • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
  • 相关阅读:
    OA项目之我的会议(会议排座&送审)
    s23.基于 Kubernetes v1.25.0(kubeadm) 和 Containerd部署高可用集群
    V100 GPU服务器安装CUDNN教程
    基于JAVA+SpringBoot的新闻发布平台
    ImmunoChemistry艾美捷总细胞毒性试验试剂盒方案
    实时行情难处理?睿凝资本选择DolphinDB解决流数据难题
    SpringBoot:速成总结+实战——员工管理系统
    三分钟学会一个新技能——使用Java操作Redis
    _cpp利用红黑树封装实现map和set
    JarFile实例多 Finalizer占用内存过大 引起的YGC时间过长 的问题排查和解决办法
  • 原文地址:https://blog.csdn.net/qq_45355603/article/details/126201940