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

嵌入式杂牌军

共 16518字,需浏览 34分钟

 ·

2021-04-17 22:16

扫描二维码

获取更多精彩

嵌入式杂牌军

                                                     

                                                  编辑|追梦星空

                                            公众号|嵌入式杂牌军


✎ 编 者 悟 语

    

     对于追求来说,再好的结果都不为过,都能接受,所以难免有不如意。



文 章 导 读


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

    阅读过程中有什么问题可以后台交流哈,


1 为什么能如此巧妙



    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中的位,再对特定的位进行一些处理,就能达到意想不到的效果。


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


2 实例代码



    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)运行结果



    今天就到这吧,希望对小伙伴有所帮助哈,喜欢的话欢迎转发、点赞、分享、在看哈,


相关推荐


宏定义中省略号在调试中的妙用


C代码实现数据通信中的转义与解析(一)转义


实用 | C代码实现数据通信中的转义与解析(二)解析


指针数组为什么不能这样初始化


数组与指针不能混用的情况


专辑分享


Linux专辑


C语言专辑


软实力专辑


软件推荐专辑



欢迎关注我的公众号,一起撸代码玩技术
浏览 18
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报