![](/img/trans.png)
[英]Is accessing to std::array<std::uint8_t, 2> while std::uint16_t is active inside a union well defined behavior?
[英]Accessing std::uint8_t as std::bitset
我想在C / C ++中为状态寄存器建模,应该以std :: bitset和std :: uint8_t对其进行访问。 因此,我将它们结合起来如下:
#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;
}
使用GCC x86_64 8.2编译时,这似乎按预期工作。 但是,我想知道我是否可以在所有情况下都能正常工作,或者我是否可以使用一些辅助功能,例如bitset
, bittest
,...
您在此处尝试使用union
操作称为type punning,并且在C ++中是Undefined Behavior(您可以在此SO Answer中了解更多信息),因此即使在同一编译器上也无法保证其正常工作。
此外,即使允许使用,也不能保证std::bitset<8>
与std::uint8_t
具有相同的表示形式(实际上,在任何主要的编译器上都没有)。
在您的情况下,您可以仅将常规的std::bitset<8>
与to_ulong
方法一起使用。
另一种选择是使用具有bitset成员的包装器类,该包装器类将提供方便的方法来分配/转换为uint8_t
。
另外,如果您只想使用std::bitset<8>
某些有限API,则最好将std::uint8_t
包裹起来并实现这几种方法(如果您希望将类的大小保持为1个字节)。 (如test
)手动。
我想到了SomeProgrammerDude的评论
对于您的问题,如果您想要一个既可以充当本机uint8_t又可以以“不错”的方式处理位的类型,那么您必须自己实现这样的类。 如果需要它映射到内存映射的硬件寄存器,则可能应该包装一个指向该寄存器的指针。
并尝试用C ++制作。 这是我想出的示例:
#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;
}
输出:
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
不过,一个独立的函数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.