【问题标题】:Can you extract bitmask directly from bitfield in C++?您可以直接从 C++ 中的位域中提取位掩码吗?
【发布时间】:2021-11-27 06:58:58
【问题描述】:

考虑以下示例:

#include <iostream>

using namespace std;

struct Test
{
    uint8_t A:1;
    uint8_t B:1;
    uint8_t C:1;
    uint8_t D:1;
};

int main()
{
    Test test;
    test.A = 1;
    test.B = 0;
    test.C = 1;
    test.D = 0;
    
    int bitmask = test.A | (test.B << 1) | (test.C << 2) | (test.D << 3);
    
    cout << "Size: " << sizeof(test) << ", bitmask: " << bitmask;

    return 0;
}

我假设位域中的数据以某种方式表示为位掩码?我想知道是否有一种方法可以直接获取位掩码,而无需遍历并移动所有成员。在这种情况下,这没什么大不了的,但如果你有很大的位域,它会变得非常乏味。

例如,如果我能做这样的事情会很棒:

int bitmask = (int)test;

这当然行不通。有什么方法可以实现类似的稳健性?

【问题讨论】:

  • “我假设位域中的数据以某种方式表示为位掩码?”这甚至没有意义。数据是一个值。位域自身有一个位掩码,定义了它在字中的范围,但它与位域中的数据完全分开。当您已经拥有位域时为什么需要该位掩码是一个谜,正如您所说的“转移所有成员”的意思。不清楚你在问什么。
  • @user207421 他想要做的是将位域的结构转换为 int,这样如果您可以将结构转换为 int,每个位长的位域都会出现在 int 中。但我确信int bitmask2 = *(int*)&amp;test; 是UB,因为它是双关语
  • @JerryJeremiah 由 OP 来澄清他的问题,而不是由我们来猜测他的意思。
  • @user207421 我没有猜到 - 我是在改写这个问题。

标签: c++ bit-fields bitmask


【解决方案1】:

假设要转换整个结构体,并且存在一个与结构体大小相同的整型:

Test test;
test.A = 1;
test.B = 0;
test.C = 1;
test.D = 0;

cout << (int)std::bit_cast<char>(test) << '\n';

std::bit_cast 是 C++20 功能。

这里使用char,因为它的大小与Test 相同。我将结果转换为int,否则cout 会将结果数字解释为字符代码。


另一种解决方案是将memcpy 结构(或其一部分)转换为整数:

char ch;
std::memcpy(&ch, &test, 1);
cout << (int)ch << '\n';

bit_cast 不同,这不需要现代编译器,并允许您检查结构的特定部分(假设该部分是字节对齐的)。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-21
    • 2019-11-19
    • 2010-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多