在 C++ 中将位域结构转换为 int

Bit Field Struct to int in C++

我有一个包含相同类型成员的结构。我正在尝试将其转换为 uint8_t 类型。我能够做到这一点,但看不到输出请告诉我哪里出错了。我也知道还有其他方法可以做到吗?我想这样做是因为我想习惯 static_castreinterpret_cast.

代码如下:

int main()
{
    struct xs{
        bool x :1 ;
        bool y :1;
        bool z :1;
        uint8_t num :5;
    } zs;

    uint8_t* P = static_cast<uint8_t*>(static_cast<void*>(&zs));

    cout << *P << endl;

    return 0;
}
  1. 通过指向对象类型以外的类型的指针访问对象是未定义的行为。它适用于大多数编译器,但从技术上讲,您的程序可以为所欲为。

  2. 假设我们没有 运行 进入 1 中提到的问题,我的猜测是 uint8_t 是 char 的别名,因此 cout 会将 char 放入您的控制台. 您没有初始化正在检查的内存,因此它可以为 0。值为零的字符不会在您的控制台中打印出任何内容 "observeable",请查看 ascii table。尝试用 50 填充结构,例如

这里有两件事需要解决。首先,正如一些人指出的那样,您不能以这种方式访问​​您的对象。如果你想正确地构造一个 uint8_t ,你需要读取你的结构中的变量并做一些位移,像这样:

uint8_t value = 0;
value |= (zs.x ? 1 << 7 : 0);
value |= (zs.y ? 1 << 6 : 0);
value |= (zs.z ? 1 << 5 : 0);
value |= zs.num;

现在,您面临的第二个问题是您正试图输出一些 8 位宽的数据。默认情况下,这被解释为 'character' 并将如此显示。为了完成您想做的事情,您可以使用不同长度的变量(uint16_t、uint32_t、...)或使用 std::to_string.

cout << std::to_string(value) << endl;

这里有很多问题:

  1. 您似乎相信 xyz 都会打包成单个 uint_8。不是这种情况。 "Adjacently declared bit fields of the same type can then be packed by the compiler into a reduced number of words"[1]
  2. "The value of sizeof(bool) is implementation defined and might differ from 1"[2] 因此您的 xs 将由实现定义,但肯定不等同于 sizeof(uint_8)
  3. 因为 xs 不是 "similar" 根据 the rules defined for C++'s type aliasinguint_8 你的 reinterpret_cast<uint_8*> 的行为未定义
  4. 最后 你看不到任何东西的原因是无论实现定义的值是什么 *P 它很可能是一个控制字符,当被 [=23= 处理时没有可见的表示] 作为 char

您所拥有的代码的一种可能的解决方法是使用这些定义:

constexpr uint8_t X = 0B1000'0000;
constexpr uint8_t Y = 0B0100'0000;
constexpr uint8_t Z = 0B0010'0000;
constexpr uint8_t NUM = 0B0001'1111;

uint8_t zs;

然后给定一些值分配给 zs 你可以执行这些函数来输出前一个位域:

cout << ((zs & X) != 0) << endl;
cout << ((zs & Y) != 0) << endl;
cout << ((zs & Z) != 0) << endl;
cout << (zs & NUM) << endl;

Live Example