当前位置: 首页 > article >正文

017__联合体和枚举

[ 基本难度系数 ]:★☆☆☆☆

一、联合体(共用体)

(1)、基本概念

联合体的外在形式跟结构体非常类似,但它们有一个本质的区别:结构体中的各个成员是各自独立的,而联合体中的各个成员却共用同一块内存,因此联合体也称为共用体。

联合体各成员的堆叠效果

联合体内部成员的这种特殊的“堆叠”效果,使得联合体有如下基本特征:

  • 整个联合体变量的尺寸,取决于联合体中尺寸最大的成员
  • 给联合体的某个成员赋值,会覆盖其他的成员,使它们失效。
  • 联合体各成员之间形成一种“互斥”的逻辑,在某个时刻只有一个成员有效。

联合体的语法:

联合体标签:用来区分各个不同的联合体。
成员:      是包含在联合体内部的数据,可以是任意的数据类型。

联合体的定义:

union 联合体标签
{
    成员1;
    成员2;
    ...
};

(2)、联合体操作

联合体的操作跟结构体形式上别无二致,

  • 初始化:
#include <stdio.h>

union node1
{
    char ch1;
    int num1;
    double f1;
    char buf1[128];
};

union node2
{
    char ch2;
    int num2;
};

struct node3
{
    int weight;
    int height;
    int id;
    union node1 other;
};



// 主函数
int main(int argc, char const *argv[])
{
    // (1)、联合体初始化
    // 1、普通初始化(只有第一个成员有效,其它将被覆盖)
    union node1 n1 = {'a', 100, 3.14, "shijienameda"};
    printf("联合体n1的值: %d\n", n1.num1);
    /*
        报警告:
            001__联合体.c:33:28: warning: excess elements in union initializer
            union node1 n1 = {'a', 100, 3.14, "shijienameda"};
                                   ^
        现象:
            打印值为97,而不是100  
    */

    // 2、指定成员初始化(只有最后一个赋值有效,其它将被覆盖)
    union node2 n2 =
    {
        .num2 = 100,
        .ch2 = 'b'
    };
    printf("联合体n2的值: %d\n", n2.num2);  
    /*                           
        现象:
            打印值为98,而不是100  
    */
    /*
        有兴趣的同学,可以去推敲一下
        union node2 n2 =
        {
            .ch2 = 'b',
            .f2 = 3.14,
            .num2 = 100                        // 内存已经变成了int型性质的内存了, 并赋值了100
        };
        printf("联合体n2的值: %d\n", n2.f2);    // 要求其打印小数数据(S、E、M)
        // 打印数据为:1

    */
    return 0;
}

- 联合体成员引用(直接使用):
at.x = 100;
at.y = 'k'; 
at.z = 3.14; // 只有最后一个赋值的成员有效

printf("%d\n", at.x);
printf("%c\n", at.y);
printf("%lf\n", at.z);
  • 联合体成员引用(直接使用):
at.x = 100;
at.y = 'k'; 
at.z = 3.14; // 只有最后一个赋值的成员有效

printf("%d\n", at.x);
printf("%c\n", at.y);
printf("%lf\n", at.z);
  • 联合体指针(间接使用):
union attr *p = &at;
p->x = 100;
p->y = 'k';
p->z = 3.14;  // 只有最后一个赋值的成员有效

printf("%d\n", p->x);
printf("%c\n", p->y);
printf("%lf\n", p->z);

(3)、联合体的使用

联合体一般很少单独使用,而经常以结构体的成员形式存在,用来表达某种互斥的属性。

  • 示例:
struct node
{
    int a;
    char b;
    double c;
    union attr at; // at内有三种互斥的属性,非此即彼
};

int main()
{
    struct node n;
    n.at.x = 100; // 使用连续的成员引用符来索引结构体中的联合体成员
}

二、枚举

枚举类型的本质是提供一种范围受限的整型,比如用0-6表示七种颜色,用0-3表示四种状态等,但枚举在C语言中并未实现其本来应有的效果,直到C++环境下枚举才拥有原本该有的属性。

  • 枚举常量列表
    • enum是关键字
    • spectrum是枚举常量列表标签,可以省略。省略的情况下无法定义枚举变量
enum spectrum{red, orange, yellow, green, blue, cyan, purple};
enum         {reset, running, sleep, stop};
  • 枚举变量
enum spectrum color = orange; // 等价于 color = 1
  • 语法要点:
    • 枚举常量实质上就是整型,首个枚举常量默认为0。
    • 枚举常量在定义时可以赋值,若不赋值,则取其前面的枚举常量的值加1。
    • C语言中,枚举等价于整型,支持整型数据的一切操作。
  • 使用举例:
switch(color)
{
    case red:
        // 处理红色...
    case orange:
        // 处理橙色...
    case yellow:
        // 处理黄色...   
}

  • 枚举数据最重要的作用,是使用有意义的单词,来替代无意义的数字,提高程序的可读性。
  • 示例代码:
#include <stdio.h>

// stm32的枚举的使用
/**
 * @brief STM32F4XX Interrupt Number Definition, according to the selected device 
 *        in @ref Library_configuration_section 
 */
typedef enum
{
    /******  Cortex-M4 Processor Exceptions Numbers ****************************************************************/
    NonMaskableInt_IRQn         = -14,    /*!< 2 Non Maskable Interrupt                                          */
    MemoryManagement_IRQn       = -12,    /*!< 4 Cortex-M4 Memory Management Interrupt                           */
    BusFault_IRQn               = -11,    /*!< 5 Cortex-M4 Bus Fault Interrupt                                   */
    UsageFault_IRQn             = -10,    /*!< 6 Cortex-M4 Usage Fault Interrupt                                 */
    SVCall_IRQn                 = -5,     /*!< 11 Cortex-M4 SV Call Interrupt                                    */
    DebugMonitor_IRQn           = -4,     /*!< 12 Cortex-M4 Debug Monitor Interrupt                              */
    PendSV_IRQn                 = -2,     /*!< 14 Cortex-M4 Pend SV Interrupt                                    */
    SysTick_IRQn                = -1,     /*!< 15 Cortex-M4 System Tick Interrupt                                */
    /******  STM32 specific Interrupt Numbers **********************************************************************/
    WWDG_IRQn                   = 0,      /*!< Window WatchDog Interrupt                                         */
    PVD_IRQn                    = 1,      /*!< PVD through EXTI Line detection Interrupt                         */
    TAMP_STAMP_IRQn             = 2,      /*!< Tamper and TimeStamp interrupts through the EXTI line             */
    RTC_WKUP_IRQn               = 3                                       
} IRQn_Type;

enum color      // 有类型,所以能定义变量
{
    red,        // 没有赋值默认是0
    orange,     // 会接上上面的值+1 == 1
    yellow,     // == 2
    green = 15, // 赋值了,所以是15
    blue,       // 会接上上面的值+1 == 16
    cyan,       // == 17
    purple      // == 18
};

// 表示状态
enum            // 没有类型,所以不能定义变量
{
    reset,      // 重启
    running,    // 运行
    sleep,      // 睡眠
    stop        // 停止
};



int main(int argc, char const *argv[])
{
    // (1)、枚举类型默认初始化
    // 1、默认不初始化(枚举类型本质就是一个整型)
    enum color c ;   // 默认为0,也有可能是乱码(看编译器)
    printf("c = %d\n", c);

    // 2、初始化
    enum color a = 1;
    printf("a = %d\n", a);

    enum color b = yellow;
    printf("b = %d\n", b);
    printf("orange = %d\n", orange);    // red颜色默认是0,后面加1,就是1
    printf("blue = %d\n", blue);        // green颜色是15,后面加1,就是16

    // (2)、在实际开发中使用(是使用有意义的单词,来替代无意义的数字,提高程序的可读性。)
    // 1、颜色选择
    enum color c_color;
    printf("请输入颜色数据:\n");
    printf("0、红色\n");
    printf("1、橙色\n");
    printf("2、黄色\n");
    scanf("%d", (int*)&c_color);
    while(getchar()!='\n');
    switch (c_color)
    {
        case red:
            printf("我是红色\n");
            break;
        case orange:
            printf("我是橙色\n");
            break;    
        case yellow:
            printf("我是黄色\n");
            break;   
        default:
            printf("我没有色\n");
            break;
    }

    // 2、机器状态选择
    int robot_status = stop;
    if (robot_status == stop)
    {
        printf("现在这个机器是停止状态\n");
    }
    
    return 0;
}


http://www.kler.cn/a/456718.html

相关文章:

  • css 关于flex布局中子元素的属性flex
  • 2024年RAG:回顾与展望
  • 结合长短期记忆网络(LSTM)和无迹卡尔曼滤波器(UKF)的技术在机器人导航和状态估计中的应用前景
  • 使用JMeter对Linux生产服务器进行压力测试
  • 【蓝桥杯选拔赛真题85】python摆放箱子 第十五届青少年组蓝桥杯python选拔赛真题 算法思维真题解析
  • 001__VMware软件和ubuntu系统安装(镜像)
  • stm32迁移
  • 【Android】GreenDao版本和Gradle版本的对应关系
  • “校园健康数据管理”:疫情管控系统的信息收集与分析
  • ID读卡器UDP协议QT小程序开发
  • Bitmap(BMP)图像信息分析主要说明带压缩的形式
  • 浏览器http缓存问题
  • 5个实用的设计相关的AI网站
  • NLP 中文拼写检测纠正论文-02-2019-SOTA FASPell Chinese Spell Checke github 源码介绍
  • 2024.12.27 周五
  • STM32-笔记13-红外避障模块-LCD1602模块
  • 基于单片机的抽油烟机自动控制无级调速电路设计
  • 智能工厂的设计软件 应用场景的一个例子:为AI聊天工具添加一个知识系统 之2
  • QML 之过渡
  • MySQL Workbench菜单汉化为中文
  • WPF使用资源定义和样式资源,解耦视图与逻辑(较多样式重复的时候使用)
  • 有没有免费提取音频的软件?音频编辑软件介绍!
  • 【深度学习基础之多尺度特征提取】特征金字塔(Feature Pyramid)是如何在深度学习网络中提取多尺度特征的?附代码
  • curl -fsSL https://get.docker.com|sh 解释命令
  • Pytorch | 利用GRA针对CIFAR10上的ResNet分类器进行对抗攻击
  • doris集群存储目录切换