如何正确从uint16_t变量中提取一个特定位
How to extract one specific bit from a uint16_t variable properly
长话短说,我目前正在用C++为一个C库编写一个包装器,该库提取嵌入式系统上寄存器的值。为了监视发生的情况,我需要读取一些寄存器的值,并为每个寄存器制作一个getter。
基本上,我希望我的方法从存储到uint16_t变量中的位返回一个布尔值。在"幼稚"和不含咖啡因的方法上,我正在做这样的事情:
bool getBusyDevice(int fd) // fd stands for file descriptor, for each instance of the class
{
uint16_t statusRegVal = 0;
get_commandReg(fd, &statusRegVal); // C-library function to get the value of status register
uint16_t shift = 0; // depends on the bit to access - for reusability
bool Busy = (bool) (statusRegVal >> shift);
return busy;
}
我对结果不太满意,我想知道是否有"适当"的方法可以做到这一点......
非常感谢您的建议!
只获取一个位的正常方法是使用按位和运算符&
。比如 statusRegVal & bitValue
.如果设置了位,则结果将等于 bitValue
,这意味着要获得布尔结果,您可以进行简单的比较:statusRegVal & bitValue == bitValue
。
因此,如果您想检查是否设置了位零(值为 0x0001
),那么您可以简单地执行
return statusRegVal & 0x0001 == 0x0001;
为了更好地了解您想要什么,请查看以下链接
屏蔽:https://en.wikipedia.org/wiki/Mask_(计算)和
位操作:https://en.wikipedia.org/wiki/Bit_manipulation
结论:如果你想在变量(寄存器)中读取特定数量的位,你应该用这个变量做一个带有位位置的MASK。假设你有 2Byte 变量 (u16Reg),你想读取位 [5,7],所以, value = ((u16Reg & 0x00A0) >> 5)
.在您的情况下,您希望读取一位并返回其状态 TRUE 或 FALSE。
value = ((u16Reg & (0x0001 << n)) >> n)
其中 n 是要读取的位号。
让我们理解一下。假设 u16Reg = 0x529D = 0b0101001010011101;位 [0] = 1 且位 [15] = 0;你想得到位 9。因此,首先确保除您的 (9) 之外的所有位均为零。
(0b0101001010011101 & (0x0001 << 9)) =
(0b0101001010011101 & 0x0200) =
(0b0101001010011101 & 0b0000001000000000) =
(0b0000001000000000) = 0x0200
这意味着 TRUE,以防您的意思是非零是 TRUE。但是,如果 TRUE 表示 0x01,则应将此位移动到 bit[0],如下所示: (0x0200 >> 9) = 0x0001
是真的 如果你能理解这一点,你可以让它更简单,比如:
value = ((u16Reg >> n) & 0x0001)
为什么不使用模板:
template<int SHIFT>
bool boolRegVal(uint16_t val) {
return val & (1 << SHIFT);
}
然后用法:
boolRegVal<4>(statusRegVal);
转换为布尔值将没有帮助,因为它不是 1 位类型。您必须清理其余位,然后检查是否有 0。
你可以做这样的事情:
bool Busy = ((statusRegVal >> shift) & 1) ? true : false;
标准库提供用于操作位的 std::bitset。这是一个示例,但我相信您可以猜到它的作用。
#include <bitset>
#include <iostream>
using namespace std;
int main(int, char**){
typedef bitset<sizeof(int)*8> BitsType; //or uint16_t or whatever
BitsType bits(0xDEADBEEF);
for(int i = 0; i < 5; ++i) //access the bits
cout << "bits[" << i << "] = " << bits[i] << 'n';
cout << "bit[3] = " << bits[3] << 'n'; //original
bits.flip(3);
cout << "bit[3] = " << bits[3] << 'n'; //b[3] = !b[3]
return 0;
}
运算符 [](size_t)
重载以返回引用,因此您也可以分配给它。 bits[4] = false
例如。最后,当玩完你的位时:)您可以转换回长(或ulong)或在您的情况下uint16_t value = static_cast<uint16_t>(bits.to_ulong())
.向标准图书馆致敬。
- 如何创建一个CMake变量,除非显式重写,否则使用默认值
- 删除一个线程上有数百万个字符串的大型哈希映射会影响另一个线程的性能
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 运行同一解决方案的另一个项目的项目
- 挂起和取消挂起一个文件DLL
- 用C++中的一个变量定义一个常量
- 函数向量_指针有不同的原型,我可以构建一个吗
- 在c++中用vector填充一个简单的动态数组
- 如何在选项卡视图Qt中设置一个新项目,并保存以前的项目
- 预处理器:插入结构名称中的前一个行号
- 我在c++代码中生成了一个运行时#3异常
- 我想将一个对T类型的非常量左值引用绑定到一个T类型的临时值
- 重新定位图像时如何前进到下一个内存块
- 如何将添加的小部件定位到基于同一布局中的另一个小部件的布局中
- 如何正确从uint16_t变量中提取一个特定位
- 将QGraphicsSvgItem的中心定位在一个位置上。
- 为什么共享库可以定位为一个用户,而不能定位为另一个用户
- 编写一个接受用户输入并定位输入文件的C程序
- 将后定位操作符增加一个以上
- 在OpenGL中定位一个对象数组