C语言位运算的封装

日期作者版本说明
2020.12.03TaoV0.01. 增加了版本记录表
2.增加了使用位域/联合体实现位操作

功能介绍

位运算

位运算就是直接对整数在内存中的二进制位进行操作,它是C语言的强大的特性之一。

功能位运算符说明
按位与a & b
按位或a | b
按位异或a ^ b位相同为0,位不同为1
按位取反~a
左移a << ba左移b位,就是a乘以2的b次方
右移a >> ba右移b位,就是a除以2的b次方

需要注意它与逻辑运算的区分。

功能逻辑运算符
逻辑与a && b
逻辑或a
逻辑非!a

在进行嵌入式开发时,常会有对寄存器进行位运算的场景。通过使用位运算,可以提高程序的执行效率,但会使代码变得生涩难懂。通过设置合适的位掩码,我们可以封装一些常用的位操作方法,如复位置位翻转取值等。以下是四种比较常用位运算的函数实现。

位域操作

有些信息在存储时,并不需要占用一个完整的字节, 而只需占几个或一个二进制位。例如在存放一个开关量时,只有0和1 两种状态, 用一位二进位即可。为了节省存储空间,并使处理简便。C语言又提供了一种数据结构,称“位域”或“位段”。所谓“位域”是把一个字节中的二进位划分为几个不同的区域,并说明每个区域的位数。每个域有一个域名,允许在程序中按域名进行操作。这样就可以把几个不同的对象用一个字节的二进制位域来表示。 位域是结构体的一种:

typedef struct
{
	uint8_t Bit0:1;
	uint8_t Bit1:1;
	uint8_t Bit2:1;
	uint8_t Bit3:1;
	uint8_t Bit4:1;
	uint8_t Bit5:1;
	uint8_t Bit6:1;
	uint8_t Bit7:1;
} BitDataStruct;

位域/联合体联用

在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作“共用体”类型结构,简称共用体,也叫联合体。联合体跟结构体的区别在于:他们外表相似,但在内存布局上存在着关键性的区别,结构体每个成员依次存储,联合体中所有成员的偏移地址都是0,也就是所有成员是叠在一起的,所以在联合体中在某一时刻,只有一个成员有效。在结构体中各成员有各自的内存空间,一个结构体变量的总长度大于等于各成员长度之和。而在联合体中,各成员共享一段内存空间,一个联合变量的长度等于各成员中最长的长度。

通过位域/联合体联用,我们可以定义一个既可以实现按位操作又能实现按字节统一操作的结构体变量。

typedef union
{
	BitDataStruct BitData;
	uint8_t ByteData;
} BitDataUnion;

定义类型

typedef struct
{
	uint8_t bit0:1;
	uint8_t bit1:1;
	uint8_t bit2:1;
	uint8_t bit3:1;
	uint8_t bit4:1;
	uint8_t bit5:1;
	uint8_t bit6:1;
	uint8_t bit7:1;
} BitDataStruct;

typedef union
{
	BitDataStruct BitData;
	uint8_t ByteData;
} BitDataUnion;

按位操作

	BitDataUnion BitData_PortCtrl;			//声明变量
	BitData_PortCtrl.BitData.bit0 = 0;		//将第0位置0

按字节操作

	BitDataUnion BitData_PortCtrl;			//声明变量
	BitData_PortCtrl.ByteData = 0x00;		//将8位全部置0

位运算封装源码

/**
 * @brief 将某个字节的某一位 置0
 * @param byte: byte need to be operated
 * @param bitNum: number of the bit
 * @retval result of the operation
 */
uint8_t BitOpt_ResetBit(uint8_t byte, uint8_t bitNum)
{
	byte &= ~(0x01<<bitNum);

	return byte;
}


/**
 * @brief 将某个字节的某一位 置1
 * @param byte: byte need to be operated
 * @param bitNum: number of the bit
 * @retval result of the operation
 */
uint8_t BitOpt_SetBit(uint8_t byte, uint8_t bitNum)
{
	byte |= (0x01<<bitNum);

	return byte;
}


/**
 * @brief 将某个字节的某一位 翻转
 * @param byte: byte need to be operated
 * @param bitNum: number of the bit
 * @retval result of the operation
 */
uint8_t BitOpt_ReverseBit(uint8_t byte, uint8_t bitNum)
{
	byte ^= (0x01<<bitNum);

	return byte;
}


/**
 * @brief 获取某个字节的某一位的值
 * @param byte: byte need to be operated
 * @param bitNum: number of the bit
 * @retval result of the operation (0 or 1)
 */
uint8_t BitOpt_GetBit(uint8_t byte, uint8_t bitNum)
{
	return (byte & (0x01<<bitNum))>>bitNum;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

全能骑士涛锅锅

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值