联合体用的多吗?

大家好,我是ZhengN。本次给分享联合体的一些知识。

联合体/共用体的使用

C语言中,联合体/共用体可以实现同一个内存空间中存储不同的数据类型(不是同时存储)。利用这个特性可以在一些情况下给我们提供便利。

比如验证大小端有很多种方法,使用联合体也可以:

#include <stdio.h>

union test
{
    int a;
    char b;
}test_u;

int main(void)
{
    test_u.a = 0x12345678;
    if (0x78 == test_u.b)
    {
        printf("Little endian\n");
    }
    else
    {
        printf("Big endian\n");
    }
    return 0;
}

再比如前两天群里有朋友问:在寄存器操作上,位域看起来似乎挺合适,但为什么库代码都基本没有使用呢?

其实TI的库中有使用,是结合共用体来使用的:

所有的寄存器被封装成联合体类型的,联合体里边的成员是一个32bit的整数及一个结构体,该结构体以位域的形式体现。这样就可以达到直接操控寄存器的某些位了。

比如,我们要设置PA0引脚的GPAQSEL1寄存器的[1:0]两位都为1,则我们只操控两个bit就可以很方便的这么设置:

GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 3

或者直接操控整个寄存器:

GpioCtrlRegs.GPAQSEL1.all |=0x03 

再比如当系统中有很多用于描述同一功能的状态变量时,传统做法可能是:

volatile uint16 iuvp = 0; // 输入欠压
volatile uint16 iovp = 0; // 输入过压
volatile uint16 iocp = 0; // 输入过流
volatile uint16 motp = 0; // 功率模块过温
volatile uint16 oovp = 0; // 输出过流

/* 判断异常及处理 */
if ((iuvp != 0) || 
 (iovp != 0) || 
 (iocp != 0) || 
 (motp != 0) || 
 (oovp != 0) 
 )
{
 // do something
}

当我们在做状态判断时,这样写下来就感觉很冗余。

换种方式:可以把这些状态变量规整到一个联合体中,用位域来描述。(以下这段代码来自:https://blog.csdn.net/weixin_44474431/article/details/102795568)

typedef union SYSTEM_FAULT{
   uint16 all;
   struct {
      uint16 iuvp:  1; // 输入欠压
      uint16 iovp:  1; // 输入过压
      uint16 iocp:  1; // 输入过流
      uint16 motp:  1; // 功率模块过温
      uint16 oovp:  1; // 输出过流
      uint16 oocp:  1; // 输出过流
      uint16 oopp:  1; // 过功率故障
      uint16 excu:  1; // 电流采样零漂过大
      uint16 cotp:  1; // CPU过温
      uint16 ilrv:  1; // 输入极性错误
  }bit;
}SYSTEM_FAULT_STRUCT;

然后状态判断可以这么做:

volatile SYSTEM_FAULT_STRUCT gPSM_FAULT;
if(gPSM_FAULT.all != 0)
{
 // do something
}

(0)

相关推荐