C小知识学习笔记(二)

        最近看到了有关结构体(struct)和联合体(union)相关的代码,突然发现这两者的结合大有妙用,故做此记录。

1.结构体(struct)

        结构体不用多说,C中非常重要的组成部分,一般的声明和定义方式如下:

// 这里先声明一个结构体
struct {
    int pro_1;
    char pro_2;
    float pro_3;
} struct_1;

// 定义一个结构体example
struct struct_1 example = {1, '1', 1.1};

        但我更喜欢另一种声明方式:

typedef struct {
    int pro_1;
    char pro_2;
    float pro_3;
} struct_1;

struct_1 example = {1, '1', 1.1};

        结构体的用法非常多,在C语言中,结合指针,甚至可以拿来模拟类(class)的用法,这点以后再说。 

2.联合体(union)

        联合体包含了一系列共用一块内存空间的成员,也被称为共用体。我认为联合体是指针外又一种操作内存的方式,具有高效地访问和修改内存的能力。指针可以直接对其指向的内存进行修改,而不用考虑原本内存上可能定义的变量等是什么。联合体也有类似的作用,其包含的一系列成员之间的关系就类似于指针,它们都互相指向了对方,因此使用一个成员修改内存,其它成员的值也就被修改了。

        联合体一般的声明和定义方式如下:

typedef union {
    uint8 pro_1[6];
    uint16 pro_2[3];
} union_1;

union_1 example;

        联合体中的成员所占的内存大小不一定要保持一致,但我们一般就是为了操作同一块内存才使用联合体,所以平时声明的时候,若没有特殊要求,尽量保持一致。 

3.结构体+联合体

        之前看到的结构体和联合体的组合,在对寄存器的定义中非常的好用。寄存器往往同一段内存会包含复数的作用,即一段2字节16位的内存,可能不仅用作控制位的存放,还可能用作数据的存放,因此使用结构体和联合体组合的方式能有效地定义寄存器之类。

        贴一小段RA6M5开发板上的 IOPORT 部分寄存器定义:

typedef struct {                                /*! R_PORT0 Structure                                          

   union {
      union {
         __IOM uint32_t PCNTR1;                    /*!  Port Control Register 1                                    

         struct {
            __IOM uint32_t PDR      : 16;           /*! Pmn Direction                                                     
            __IOM uint32_t PODR     : 16;           /*! Pmn Output Data                                                  
         } PCNTR1_b;
      } ;

      struct {
         union {
            __IOM uint16_t PODR;                    /*!<  Output data register                                       

            /* ... 代码过长省略 ... */
         } ;

         union {
            __IOM uint16_t PDR;                     /*!<  Data direction register                                    

            /* ... 代码过长省略 ... */
         } ;
      };
   };

   union {
      union {
         __IM  uint32_t PCNTR2;                    /*!<  Port Control Register 2                                    

         struct {
            __IM  uint32_t PIDR     : 16;           /*! Pmn Input Data                                                    
            __IM  uint32_t EIDR     : 16;           /*!Pmn Event Input Data                                             
         } PCNTR2_b;
      } ;

      struct {
         union {
            __IM  uint16_t EIDR;                    /*! Event input data register                                  

            /* ... 代码过长省略 ... */
         } ;

         union {
            __IM  uint16_t PIDR;                    /*! Input data register                                        
            /* ... 代码过长省略 ... */
         } ;
      };
   };
   /* ... 代码过长省略 ... */
} R_PORT0_Type;                                 

        可以看到,最外围是R_POTR0_Type的结构体:

typedef struct { 
    成员
} R_PORT0_Type;

         而内部成员则根据寄存器不同地址段的作用分为了各个联合体,而成员联合体内有嵌套了结构体和联合体:

内部成员:
    union_1 {
        union_1_1{
            XXX
        }
        struct_1_1{
            XXX
        }
    }

    union_2 {
        union_2_1{
            XXX
        }
        struct_2_1{
            XXX
        }
    }

       其中,为了更好的定义每一位的作用,还使用了位域操作,将一个uint32类型(32位)分为了低16位和高16位,分别定义了两个成员:

struct {
    __IOM uint32_t PDR      : 16;           /*!< [15..0] Pmn Direction                                                     
    __IOM uint32_t PODR     : 16;           /*!< [31..16] Pmn Output Data                                                  
} PCNTR1_b;

        以这种层层嵌套与组合的方式,就可以将一个具有多种功能的寄存器清晰地定义出来。 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值