• 25.0、C语言——自定义数据类型_枚举和共用体


    25.0、C语言——自定义数据类型_枚举和共用体

    枚举的定义:

    1. enum Sex {
    2. // 枚举的可能取值——常量
    3. MALE,
    4. FEMALE,
    5. SECRET
    6. };
    7. int main() {
    8. enum Sex s = MALE;
    9. printf("%d %d %d",MALE,FEMALE,SECRET);
    10. return 0;
    11. }

            1. 我们会发现打印出来的值是 -> 0 1 2 , 因为枚举常量默认从 0 开始依次往下递增;
            2. 当然枚举变量默认的值也可以修改,只需要在枚举类中定义枚举常量的时候用 ' = ' 赋予初始值即可;
            3. 那么由于枚举类型的变量每次赋值的内容只能是一个,并且还是一个整型,所以枚举类型的对象就是一个整型的大小,也就是 4 字节;

    枚举的优点:

    我们可以使用 #define 定义常量,为什么非要使用枚举?

            1. 增加代码的可读性和可维护性;
            2. 和 #define 定义和标识符相比枚举有类型检查,更加严谨;
            3. 防止命名污染(封装);
            4. 便于调试;【因为 -> 如果用#define a 1,此时定义了一个常量a = 1,当我们调试的时候看到是 1 ,而不是 a ,因为C语言在预处理的阶段会把 a 转换为 1;那当我们定义的常量比较多有比较复杂的时候,不利于我们对程序的观察和阅读;】
            5. 使用方便,一次可以定义多个常量;

    联合(共用体)

    联合类型的定义:

            联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以也叫联合体);比如 ->

    先来看一段代码:

    1. union Un {
    2. char c;
    3. int i;
    4. };
    5. int main() {
    6. union Un u;
    7. printf("%p\n",&u);
    8. printf("%p\n", &(u.c));
    9. printf("%p\n", &(u.i));
    10. return 0;
    11. }

            1. 输出结果可以发现都是一样的地址内存空间;
            2. 说明变量 c 和 变量 a 同时共用同一块内存空间;

            但是我们会发现由于联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少应该是联合体中最大成员变量的大小(因为联合至少得有能力保存最大的那个成员的空间);
            那么联合体的使用条件也是比较苛刻的,像上面联合体中的两个成员 c 和 i 不能同时使用,因为他们共用一块空间,修改一个另一个也会受到影响;

    之前我们做过一道笔试题 -> 设计一个函数 check() 来测试机器的存储方式(小端/大端字节序存储模式);
    我们用 char* 指针解决了这个问题,这次我们巧用 union 联合体来解决,实现代码如下所示:

    1. int check() {
    2. union Un {
    3. int i;
    4. char c;
    5. }u;
    6. u.i = 1;
    7. return u.c;
    8. }
    9. int main() {
    10. if (check() == 1) {
    11. printf("小端字节序存储模式");
    12. }
    13. else {
    14. printf("大端字节序存储模式");
    15. }
    16. return 0;
    17. }

            1. check() 函数中先声明了一个 union 联合体 Un,并创建了一个联合体对象 u;
            2. 在联合体中定义了两个变量 char c; 和 int i; ,并且给 i 赋值 1;
            3. 由于 i 是整型变量 4 个字节,但是 c 是字符类型 1 字节,他们又共用同一块空间,所以 访问 u.c 其实访问的就是 i 的第一个字节空间的内容;
            4. 小端存储数字1 :01 00 00 00          大端存储数字1 :00 00 00 01
            5. 所以我们只需要看 u.c 访问的是 1 还是 0 就知道该机器是小端还是大端字节序存储模式了;

    联合体大小如何计算:

    1. 联合的大小至少是最大成员的大小;

    2. 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍;

    比如 ->

    1. union Un {
    2. int i; // 4 < 8 所以对齐数是 4
    3. char arr[5]; // 1 < 8 所以对齐数是 1
    4. };
    5. int main() {
    6. union Un u;
    7. printf("%d\n",sizeof(u));
    8. return 0;
    9. }

             1. 这里的联合体虽然 5 个字节就已经够用了,但是发现最大的对齐数是 4 (虽然char arr[5] 数组大小是 5 字节,但是每个元素的大小是 1 字节,所以对齐数是 1 );
             2. 那么由于规定联合体的大小必须是最大对齐数的整数倍,5 不是 4 的整数倍所以再往后加 3 个字节 5 + 3 变成 8,8 是 4 的整数倍,所以该联合体的大小是 8 字节

  • 相关阅读:
    中国储运杂志中国储运杂志社中国储运编辑部2022年第7期目录
    Excel自定义排序和求和
    javaWeb项目-邮票鉴赏系统功能介绍
    ThingsBoard IoT Gateway 实战(一)- 入手
    界面组件Kendo UI for Vue 2024 Q2亮点 - 发布一系列新组件
    Linux常用指令--查找指令
    逮到一个阿里10年老测试员,聊过之后收益良多...
    【Java】工作中常用的一些lambda表达式
    请问一下测试过来人,现在学来得及吗😫
    LeetCode 2349. 设计数字容器系统(SortedSet)
  • 原文地址:https://blog.csdn.net/m0_52433668/article/details/126914919