zoukankan      html  css  js  c++  java
  • C语言学习之联合类型

    前言

    联合(union)是一种特殊的数据类型,和结构体很像,结构体各成员变量有自己独立的存储位置,而联合的成员变量共享同一片存储区域,因此联合变量再一个时刻只能保存它的某一个成员的值。

    联合的定义和初始化

    联合的定义方式与结构体是一样的,只是把关键字 struct 改成 union:

    union [标签名称]
    {
    	成员声明列表
    };
    

    下面的例子定义了一个名为Data的联合类型,它有 3 个成员:i、x 和 str:

    union Data 
    { 
    	int i; 
    	double x; 
    	char str[16]; 
    };
    

    这种类型的对象可以存储一个整数、一个浮点数或一个短字符串。

    下面的声明定义了一个 union Data 类型的对象 var 和一个 unionData 类型的数组 myData,它有 100 个元素(联合的空间大小为它最大成员的空间大小):

    union Data var, myData[100];
    

    联合成员值的获取和修改

    获取联合成员值的方式和获取结构体成员的方式一样。但是与结构体不同的是,当改变一个联合成员的值时,实际上修改了该联合所有成员的值。

    联合的初始化

    与结构一样,C99 允许在初始化器中使用成员指示符来指示哪个成员被初始化。而且,如果初始化器没有成员指示符,那么就与联合内的第一个成员关联。具有自动存储类的联合对象也可以使用已有的同类型对象来初始化。下面是一些初始化例子:

    union Data var1 = { 77 },
               var2 = { .str = "Mary" },
               var3 = var1,
               myData[100] = { {.x= 0.5}, { 1 }, var2 };
    

    数组 myData 中的元素如果没有指定初始化器,会被隐式地初始化为 0 值。

    union的应用:浮点型转换为4字节整型

    在串口、IIC、SPI等数据传送时,基本上都是一次传送一个字节的数据,如果我们要传送的是浮点类型的数据呢?常用的方法是将浮点数乘以一个倍数,如10,100,1000,10000等,然后将其转换为整型数据再转化为单个字节进行传送。如果这个数据是要进行显示的话,那么这样做并没有什么不好。但是如果这个数是要传输给另端进行继续计算的话,那么就要考虑另一种方法了,就是直接将浮点数据转换为4个单字节,在另一端接受完数据后再转化为浮点数据,这种方式不会造成精度的丢失,计算量也比较小。

    【示例程序】:

    #include <stdio.h>
    
    typedef union
    {
        float fdata;        //fdata和ldata共用存储空间
        int ldata;
    } FloatLongType;
    
    //将浮点数f转化为4个字节数据存放在byte[4]中
    void Float_to_Byte(float f,unsigned char byte[])
    {
        FloatLongType fl;
        fl.fdata=f;
        byte[0]=(unsigned char)fl.ldata;
        byte[1]=(unsigned char)(fl.ldata>>8);
        byte[2]=(unsigned char)(fl.ldata>>16);
        byte[3]=(unsigned char)(fl.ldata>>24);
    }
    
    //将4个字节数据byte[4]转化为浮点数存放在*f中
    void Byte_to_Float(float *f,unsigned char byte[])
    {
        FloatLongType fl;
        fl.ldata=0;
        fl.ldata=byte[3];
        fl.ldata=(fl.ldata<<8)|byte[2];
        fl.ldata=(fl.ldata<<8)|byte[1];
        fl.ldata=(fl.ldata<<8)|byte[0];
        *f=fl.fdata;
    }
    
    int main()
    {
        float f=123456.781234;    //要转换的浮点数
        unsigned char byte[4]= {0}; //转换后的4个字节数据存放的数组
    
        printf("float data=%f
    ",f);
        //float 转换为 4个字节数据
        Float_to_Byte(f,byte);
        //输出转换后的4个字节数据
        printf("%f to : %x %x %x %x 
    ", f, byte[0], byte[1], byte[2], byte[3]);
        //把byte的4个字节数据转换为float
        Byte_to_Float(&f,byte);
        printf("float data=%f
    ",f);        //输出转换后的结果
    
        return 0;
    }
    

    【输出结果】:

    float data=123456.781250
    123456.781250 to : 64 20 f1 47
    float data=123456.781250
    

    可以看出,浮点型数据123456.781250被转换成了64-20-f1-47,4个字节的数据。

    不使用联合将单精度浮点型转换成4个字节

    在使用单片机和匿名上位机通信,当传输的是一个float类型的数据时,我们需要将float类型数据转换为4个字节的char类型然后通过串口发出去才可以正常显示,

    以下是我写的一个函数,不使用联合,可以把一个浮点型数据转换成4个字节的数据,然后通过串口发送出去:

    //一个单精度浮点数据的发送
    void ANO_SendFloat(int channel, float f_dat)
    {
        u8 tbuf[8];
        int i;
        unsigned char *p;
    
        for(i = 0; i <= 7; i++)
            tbuf[i] = 0;
    
        p=(unsigned char *)&f_dat;		
        tbuf[0] = 0x88;
        tbuf[1] = channel;  //0xA1
        tbuf[2] = 4;
        tbuf[3]=(unsigned char)(*(p+3));        //取float类型数据存储在内存中的四个字节
        tbuf[4]=(unsigned char)(*(p+2));
        tbuf[5]=(unsigned char)(*(p+1));
        tbuf[6]=(unsigned char)(*(p+0));
    
        for(i=0; i<=6; i++)
            tbuf[7] += tbuf[i];     //校验和
    //printf("%s",tbuf);		//串口发送字符串
    }
    

    参考资料:

    历史精选文章:


    欢迎大家关注我的个人博客

    或微信扫码关注我的公众号

  • 相关阅读:
    mysql索引
    mysql中的事务
    mysql的各种join连接
    java集合-LinkedList源码分析
    java集合(二)-ArrayList源码分析
    java集合(一)-集合概述
    java并发(五)-重排序、 happens-before
    vue引入百度地图 --BMap is not defined ,eslint BMap报错
    红星美凯龙前端面试内容总结
    vue父子组件钩子函数的执行顺序
  • 原文地址:https://www.cnblogs.com/whik/p/10443027.html
Copyright © 2011-2022 走看看