简体   繁体   English

在结构中使用union的目的是什么?

[英]What purpose to use union in struct?

I'm currently struggling with uart snippet codes from embedded UART program. 我目前正在努力处理嵌入式UART程序中的uart代码段代码。

Then I came across what I can't undersatnd when I analysing code. 然后我在分析代码时遇到了我不能理解的事情。

Q1. Q1。 In case of using "union" in "struct". 如果在“结构”中使用“联合”。 what is the benefit and what purpose to use like this? 这样使用有什么好处和目的?

#define     __IO    volatile   

typedef struct {
  union {
  __IO  uint32_t RR;
  __IO  uint32_t TR;
  __IO  uint32_t DL;
  __IO  uint32_t RR_TR_DL;
  };
  union {
  __IO  uint32_t DH;
  __IO  uint32_t IR;  
  __IO  uint32_t DH_IER;
  };
} UART_TypeDef;

Q2. Q2。 In case of using "union" in "struct" in "struct". 如果在“结构”的“结构”中使用“联合”。 what is the benefit and what purpose to use like this? 这样使用有什么好处和目的?

typedef struct {
  union {
  struct{
    __IO   uint32_t CTRLR0; 
    __IO   uint32_t SSI_COMP_VERSION;  
    union {
    __IO   uint32_t DR;              
    __IO   uint32_t DR0;            
    };
    __IO   uint32_t DR1;            
    __IO   uint32_t RSVD_2;       
  };
  uint8_t RESERVED[0x1000];     
  };
} SSI_TypeDef;

The first case is basically "aliasing" of the field names. 第一种情况基本上是字段名称的“别名”。 The UART_TypeDef type consists of two uint32_t fields, the first which can be referred to as any of RR , TR , DL or RR_TR_DL . UART_TypeDef类型包含两个uint32_t字段,第一个可以称为RRTRDLRR_TR_DL任何一个。 Ditto for the second field, which can be DH , IR or DH_IER . 第二字段的同上,可以是DHIRDH_IER

The second case, SSI_TypeDef , is similar in respect to the inner unions, consisting of three uint32_t fields, CTRLR0/SSI_COMP_VERSION , DR/DR0 and DR1/RSVD_2 (in all cases, either name can be used for the fields). 第二种情况SSI_TypeDef内部联合类似,由三个uint32_t字段CTRLR0/SSI_COMP_VERSIONDR/DR0DR1/RSVD_2 (在所有情况下,任何一种名称都可以用于这些字段)。

But the structure as a whole is sized at 4K, due to the unioning with uint8_t RESERVED[0x1000] . 但由于与uint8_t RESERVED[0x1000]的结合,整个结构的大小为4K。


The aliasing is useful if, for example, the same underlying field can be accessed as either RR or TR , depending on context. 例如,如果根据上下文可以访问与RRTR相同的基础字段,则别名非常有用。 For example, a device may have different behaviour depending on whether you read or write the location. 例如,取决于您是读取还是写入位置,设备可能具有不同的行为。

Say, for example, that you write to a given address (a memory mapped I/O operation) to indicate to the other end that you are read-ready (able to receive data). 例如,假设您写入给定地址(内存映射的I / O操作),以指示另一端您已准备就绪(可以接收数据)。 Further assume that reading that exact same location will let you know whether you're able to transmit. 进一步假设读取完全相同的位置将使您知道您是否能够传输。

First, let's set up said memory mapped I/O address (say it's at 0xf000 ): 首先,让我们设置内存映射的I / O地址(假设它位于0xf000 ):

UART_TypeDef *utd = (UART_TypeDef *)0xf000; // very shifty :-)

Now both these statement refer to the same memory address: 现在, 两个语句都指向相同的内存地址:

int transmitReady = utd->TR; // Can I transmit?
utd->RR = 1;                 // Tell other end it can send.

Being able to use distinct names for the same underlying thing can aid readability. 能够对同一基础事物使用不同的名称可以提高可读性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM