力荐 | 结构体位域与联合的巧妙结合:实现位散写,字节读(散存整取)

在这里插入图片描述

作者|釜薪君
公众号|嵌入式杂牌军



前言


位域操作常用于逐位定义参量,再加上连个地址共用的特性,能实现散存整取的效果,很不错呦。


一、为什么能如此巧妙


1.位域操作


位域操作可以指定具体字节位的意义,如下面结构所示。

typedef struct 
{
     uint8_t   color   :1; // 颜色——1:红  , 0:绿 
     uint8_t   length  :1; // 长度——1:20cm , 0:10cm
     uint8_t   width   :1; // 宽度——1:10cm , 0:5cm
     uint8_t   hight   :1; // 高度——1:2cm  , 0:1cm
     uint8_t   bit5    :1; // 未定义 
     uint8_t   bit6    :1; // 未定义 
     uint8_t   bit7    :1; // 未定义 
     uint8_t   Flag    :1; // 标志——1:有货, 0:缺货 
} ProductST;

实际中CAN数据位结构就是我们比较常见的一种位域。

2.联合


联合又称为共用体,它的成员共用一个地址。

typedef union 
{
     uint8_t   Byte;        // 取整个字节进行操作 
     ProductST Bits;        // 位成员,单个位的操作 
} ProductUN;


可以像上面一样定义一联合,它有两个成员,其中ProductST类型的Bits可以用于位域的赋值操作。

由于Bits与Byte地址共用,所以读取Byte变量即可读取Bits中的位,再对特定的位进行一些处理,就能达到意想不到的效果。


下面我用一个模拟产品库存有无的代码来实现一下“散存整取”的效果。

二、实例代码


1.实例代码


说明都在代码注释中了。


#include <stdio.h>
#include <stdlib.h>
#include <stdint.h> 

#define Color_Red    1
#define Color_Green  0

#define Length_20cm  1
#define Length_10cm  0

#define Width_10cm   1
#define Width_5cm    0

#define Hight_2cm    1
#define Hight_1cm    0

#define InStock      1
#define OutOfStock   0


// 信息:最高位为标志,剩下7为参数位 
typedef struct 
{
     uint8_t   color   :1; // 颜色——1:红  , 0:绿 
     uint8_t   length  :1; // 长度——1:20cm , 0:10cm
     uint8_t   width   :1; // 宽度——1:10cm , 0:5cm
     uint8_t   hight   :1; // 高度——1:2cm  , 0:1cm
     uint8_t   bit5    :1; // 未定义 
     uint8_t   bit6    :1; // 未定义 
     uint8_t   bit7    :1; // 未定义 
     uint8_t   Flag    :1; // 标志——1:有货, 0:缺货 
} ProductST;


// 联合->共用体->利用地址共用的特点,Bits用于位写,Byte用于字节读 
typedef union 
{
     uint8_t   Byte;        // 取整个字节进行操作 
     ProductST Bits;        // 位成员,单个位的操作 
} ProductUN;


int main(int argc, char *argv[]) 
{
     uint8_t i,j;
 
     ProductUN   ProArray[10] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00};
 
 
      // 有货的三个 
      ProArray[0].Bits.color = Color_Red;       // 红色    1
      ProArray[0].Bits.length = Length_20cm;    // 长20cm  1
      ProArray[0].Bits.width = Width_10cm;      // 宽10cm  1
      ProArray[0].Bits.hight = Hight_2cm;       // 高2cm   1
 
      ProArray[1].Bits.color = Color_Red;       // 红色    1
      ProArray[1].Bits.length = Length_20cm;    // 长20cm  1
      ProArray[1].Bits.width = Width_10cm;      // 宽10cm  1
      ProArray[1].Bits.hight = Hight_1cm;       // 高2cm   0
 
      ProArray[2].Bits.color = Color_Red;       // 红色    1
      ProArray[2].Bits.length = Length_20cm;    // 长20cm  1
      ProArray[2].Bits.width = Width_5cm;       // 宽50cm  0
      ProArray[2].Bits.hight = Hight_1cm;       // 高1cm   0
 
      // 没货的两个 
      ProArray[3].Bits.color = Color_Red;       // 红色    1
      ProArray[3].Bits.length = Length_20cm;    // 长20cm  1
      ProArray[3].Bits.width = Width_5cm;       // 宽50cm  0
      ProArray[3].Bits.hight = Hight_2cm;       // 高2cm   1
 
      ProArray[4].Bits.color = Color_Green;     // 绿色    0
      ProArray[4].Bits.length = Length_20cm;    // 长20cm  1
      ProArray[4].Bits.width = Width_5cm;       // 宽50cm  0
      ProArray[4].Bits.hight = Hight_2cm;       // 高2cm   1
 
 for(i = 0; i < 5; i++) 
 {
        /* 库存中有货的规格 */ 
       if(   ((ProArray[i].Byte & 0x0F) == 0x0F)     
          || ((ProArray[i].Byte & 0x0F) == 0x07) 
          || ((ProArray[i].Byte & 0x0F) == 0x03))   
         {
              ProArray[i].Bits.Flag = InStock;
              printf("You product is :\n\n");  
     
              if(ProArray[i].Bits.color)
              {
                   printf("Color_Red");
              } 
              else
              {
                   printf("Color_Green");
              }  
    
              if(ProArray[i].Bits.length)
              {
                   printf(" x Length_20cm");
              } 
              else
              {
                   printf(" x Length_10cm");
              }  
       
              if(ProArray[i].Bits.width)
              {
                   printf(" x Width_10cm");
              } 
              else
              {
                   printf(" x Width_5cm");
              }
    
              if(ProArray[i].Bits.hight)
              {
                   printf(" x Hight_2cm\n\n");
              } 
              else
              {
                   printf(" x Hight_1cm\n\n");
              }     
         }
         else
         {
              ProArray[i].Bits.Flag = OutOfStock;
              printf("\nThe product is out of stock!\n\n");
   
              if(ProArray[i].Bits.color)
              {
                   printf("Color_Red");
              } 
              else
              {
                   printf("Color_Green");
              }  
   
              if(ProArray[i].Bits.length)
              {
                   printf(" x Length_20cm");
              } 
              else
              {
                   printf(" x Length_10cm");
              }  
      
              if(ProArray[i].Bits.width)
              {
                   printf(" x Width_10cm");
              } 
              else
              {
                   printf(" x Width_5cm");
              }
   
              if(ProArray[i].Bits.hight)
              {
                   printf(" x Hight_2cm\n\n");
              } 
              else
              {
                   printf(" x Hight_1cm\n\n");
              }     
         }
     }
 
     return 0;
}


2.运行结果


在这里插入图片描述


今天就到这吧,希望对小伙伴有所帮助哈!


欢迎关注公众号~

在这里插入图片描述

  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值