作者|釜薪君
公众号|嵌入式杂牌军
前言
位域操作常用于逐位定义参量,再加上连个地址共用的特性,能实现散存整取的效果,很不错呦。
一、为什么能如此巧妙
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.运行结果
今天就到这吧,希望对小伙伴有所帮助哈!
欢迎关注公众号~