为什么位模式与 std::bitset 的使用不匹配

Why are the bit patterns not matching with the use of std::bitset

当我对我的 class 及其构造函数进行单元测试时,我注意到我的输出有些奇怪。

#include <bitset>
#include <cstdint>
#include <iostream>
#include <vector>

typedef std::uint8_t u8;
typedef std::uint16_t u16;
typedef std::uint32_t u32;
typedef std::uint64_t u64;

struct Reg8 {
    std::bitset<8> bits;
    u8 value;

    Reg8() : value{0}, bits{value} {}

    explicit Reg8( u8 val) : value{val}, bits{value} {}
    explicit Reg8(u16 val) : value{static_cast<u8>(val)}, bits{value} {}
    explicit Reg8(u32 val) : value{static_cast<u8>(val)}, bits{value} {}
    explicit Reg8(u64 val) : value{static_cast<u8>(val)}, bits{value} {}    
};

int main() {
    u8  val8  = 24;
    u16 val16 = 24;
    u32 val32 = 24;
    u64 val64 = 24;

    Reg8 r8a(val8);
    Reg8 r8b(val16);
    Reg8 r8c(val32);
    Reg8 r8d(val64);

    std::cout << "Reg8(u8)  r8a value = " << +r8a.value << '\n';
    std::cout << "Reg8(u8)  r8a bits  = " << r8a.bits << "\n\n";

    std::cout << "Reg8(u16) r8b value = " << +r8b.value << '\n';
    std::cout << "Reg8(u16) r8b bits  = " << r8b.bits << "\n\n";

    std::cout << "Reg8(u32) r8c value = " << +r8c.value << '\n';
    std::cout << "Reg8(u32) r8c bits  = " << r8c.bits << "\n\n";

    std::cout << "Reg8(u64) r8d value = " << +r8d.value << '\n';
    std::cout << "Reg8(u64) r8d bits  = " << r8d.bits << "\n\n";

    std::bitset<8> bitsA{ val8 };
    std::cout << "bits value  = " << bitsA.to_ullong() << '\n';
    std::cout << "bits binary = " << bitsA << "\n\n";

    std::bitset<8> bitsB{ val16 };
    std::cout << "bits value  = " << bitsB.to_ullong() << '\n';
    std::cout << "bits binary = " << bitsB << "\n\n";

    std::bitset<8> bitsC{ val32 };
    std::cout << "bits value  = " << bitsC.to_ullong() << '\n';
    std::cout << "bits binary = " << bitsC << "\n\n";

    std::bitset<8> bitsD{ val64 };
    std::cout << "bits value  = " << bitsD.to_ullong() << '\n';
    std::cout << "bits binary = " << bitsD << "\n\n";

    return EXIT_SUCCESS;
}

这是我的输出来自一个小端机器和 Intel Quad Core Extreme 运行 Windows 7 x64 并使用 Visual Studio x64 调试模式下的 2017 CE,编译器语言选项设置为 c++ 最新草案标准。所有其他编译器标志 - 优化等 Visual Studio 的默认值。

Reg8(u8)  r8a value = 24
Reg8(u8)  r8a bits  = 11001100

Reg8(u16) r8b value = 24
Reg8(u16) r8b bits  = 11001100

Reg8(u32) r8c value = 24
Reg8(u32) r8c bits  = 11001100

Reg8(u64) r8d value = 24
Reg8(u64) r8d bits  = 11001100

bits value  = 24
bits binary = 00011000

bits value  = 24
bits binary = 00011000

bits value  = 24
bits binary = 00011000

bits value  = 24
bits binary = 00011000

那么为什么 class 结构中的位模式与 main 中声明的位模式不匹配?

我使用相同的变量类型和值来初始化 main 中的位集以及 class 中的位集,但它们的位模式不匹配。 class里面的都一样,class外面的都一样。

我期望看到的和我想要的值应该是在 main 中看到的值。当我查看输出的下半部分时,main 中的这些 bitset 变量的值为 24 并且它们的位模式匹配 24 的 8 位。

0001 1000 = 24

然而,存储在我的 class 中位集中的位模式不匹配,但包含适当的值。存储在我的 class 中的位集具有位模式

1100 1100  ... doesn't = 24 in binary

这是怎么回事?

请记住,成员初始化列表按声明顺序进行初始化。意思是:

struct Reg8 {
    std::bitset<8> bits; // <- first to be initialized in mem-init-list
    u8 value; // <- second

};

并以此构造函数为例:

explicit Reg8(u16 val) : value{static_cast<u8>(val)}, bits{value} {}

初始化列表的顺序无关紧要。 bits 在声明中出现在 value 之前,因此 bits 将首先被初始化。它将被初始化为 value,它仍未初始化,因为 value{static_cast<u8>(val)}bits.

初始化之后出现

要解决此问题,请交换声明:

struct Reg8 {
    u8 value;
    std::bitset<8> bits;
};

旁注:您的代码中缺少 stdint 包含。