[英]Accessing std::uint8_t as std::bitset
I would like to model a status register in C/C++, which should be accessible as std::bitset and as std::uint8_t . 我想在C / C ++中为状态寄存器建模,应该以std :: bitset和std :: uint8_t对其进行访问。 Thus I would combine them as union as follows:
因此,我将它们结合起来如下:
#include <bitset>
#include <iostream>
union byte {
std::uint8_t uint;
std::bitset<8> bitset;
};
int main(int, char*[])
{
byte b = { .uint = 0b10101010 };
std::cout << "Value of bit 5: "
<< (b.bitset.test(5) ? "true" : "false") << std::endl;
std::cout << "Value of bit 4: "
<< (b.bitset.test(4) ? "true" : "false") << std::endl;
std::cout << "Bitset Output: " << b.bitset << std::endl;
std::cout << "Uint Output: " << static_cast<int>(b.uint) << std::endl;
return 0;
}
This seems to work as expected, when compiled with GCC x86_64 8.2 . 使用GCC x86_64 8.2编译时,这似乎按预期工作。 However, I would like to know if I could expect this to work in all cases or if I am better off with some helper functions like
bitset
, bittest
, ... 但是,我想知道我是否可以在所有情况下都能正常工作,或者我是否可以使用一些辅助功能,例如
bitset
, bittest
,...
What you are trying to do here with union
is called type punning and is Undefined Behavior in C++ (you can read more about it in this SO answer ), so it's not guaranteed to work properly even on the same compiler. 您在此处尝试使用
union
操作称为type punning,并且在C ++中是Undefined Behavior(您可以在此SO Answer中了解更多信息),因此即使在同一编译器上也无法保证其正常工作。
Furthermore, even if it was allowed, std::bitset<8>
is not guaranteed to have the same representation as std::uint8_t
(and in fact it does not on any major compiler). 此外,即使允许使用,也不能保证
std::bitset<8>
与std::uint8_t
具有相同的表示形式(实际上,在任何主要的编译器上都没有)。
In your case, you could just use the regular std::bitset<8>
with to_ulong
method. 在您的情况下,您可以仅将常规的
std::bitset<8>
与to_ulong
方法一起使用。
Another alternative is to have a wrapper class with bitset member that would provide convenience methods to assign/convert to uint8_t
. 另一种选择是使用具有bitset成员的包装器类,该包装器类将提供方便的方法来分配/转换为
uint8_t
。
Also, if you only want some limited API of std::bitset<8>
, it might be good idea (if you want to keep the size of your class as 1 byte) to wrap around std::uint8_t
and implement those few methods (like test
) manually. 另外,如果您只想使用
std::bitset<8>
某些有限API,则最好将std::uint8_t
包裹起来并实现这几种方法(如果您希望将类的大小保持为1个字节)。 (如test
)手动。
I took the idea of SomeProgrammerDude's comment 我想到了SomeProgrammerDude的评论
As for your problem, if you want a type that can act as both a native uint8_t and handle bits in a "nice" way, then you have to implement such a class yourself.
对于您的问题,如果您想要一个既可以充当本机uint8_t又可以以“不错”的方式处理位的类型,那么您必须自己实现这样的类。 If you need it to map to a memory-mapped hardware register it should probably wrap a pointer to the register.
如果需要它映射到内存映射的硬件寄存器,则可能应该包装一个指向该寄存器的指针。
and tried to make it in C++. 并尝试用C ++制作。 This is the sample I came up with:
这是我想出的示例:
#include <cassert>
#include <iostream>
#include <iomanip>
class ByteReg {
private:
volatile uint8_t ®
public:
explicit ByteReg(volatile uint8_t ®): reg(reg) { }
ByteReg(const ByteReg&) = delete;
ByteReg operator=(const ByteReg&) = delete;
~ByteReg() = default;
operator uint8_t() { return reg; }
bool test(int i) const
{
assert(i >= 0 && i < 8);
return ((reg >> i) & 1) != 0;
}
};
int main()
{
volatile uint8_t hwReg = 0xaa; // 0x10101010
ByteReg reg(hwReg);
unsigned value = reg;
std::cout << "reg: 0x" << std::hex << std::setw(2) << std::setfill('0')
<< value << '\n';
for (int i = 0; i < 8; ++i) {
std::cout << "bit " << i << ": "
<< (reg.test(i) ? "set" : "unset") << '\n';
}
return 0;
}
Output: 输出:
reg: 0xaa
bit 0: unset
bit 1: set
bit 2: unset
bit 3: set
bit 4: unset
bit 5: set
bit 6: unset
bit 7: set
Live Demo on coliru 在coliru上进行现场演示
Though, a free-standing function testBit()
might do as well with even less code: 不过,一个独立的函数
testBit()
甚至可以用更少的代码来完成:
#include <cassert>
#include <iostream>
#include <iomanip>
bool testBit(uint8_t reg, int i)
{
assert(i >= 0 && i < 8);
return ((reg >> i) & 1) != 0;
}
int main()
{
volatile uint8_t reg = 0xaa; // 0x10101010
unsigned value = reg;
std::cout << "reg: 0x" << std::hex << std::setw(2) << std::setfill('0')
<< value << '\n';
for (int i = 0; i < 8; ++i) {
std::cout << "bit " << i << ": "
<< (testBit(reg, i) ? "set" : "unset") << '\n';
}
return 0;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.