1

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

#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;
}

这是我的输出来自运行 Windows 7 x64 并在 x64 调试模式下使用 Visual Studio 2017 CE 的 little endian 机器和 Intel Quad Core Extreme,编译器语言选项设置为 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

那么为什么类构造中的位模式与 main 中声明的位模式不匹配呢?

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

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

0001 1000 = 24

但是,存储在我的类中的位集中的位模式不匹配,但包含适当的值。存储在我的班级中的位集具有位模式

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

这里发生了什么?

4

1 回答 1

3

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

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的代码中缺少包含。

于 2019-05-12T15:07:05.577 回答