【问题标题】:Why are the bit patterns not matching with the use of std::bitset [duplicate]为什么位模式与使用 std::bitset 不匹配 [重复]
【发布时间】:2019-09-29 17:07:05
【问题描述】:

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

#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 并使用 x64 调试模式下的 Visual Studio 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

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

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

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

0001 1000 = 24

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

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

这是怎么回事?

【问题讨论】:

    标签: c++ output c++17 std-bitset


    【解决方案1】:

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

    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&lt;u8&gt;(val)} 是在bits 初始化之后出现的。

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

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

    旁注:您的代码中缺少stdint

    【讨论】:

    • 我不需要&lt;stdint&gt; 我包括&lt;vector&gt;,这为我提供了std::uintx_t 类型,其中x = 8,16,32,64
    • @FrancisCugler 规范未指定。该规范在stdint 标头中有这些,您很幸运&lt;vector&gt; 的实现包含该标头。你不能假设。
    • 哦,好吧,我不知道。因此,对我来说,要使其具有可移植性和通用性,只需将该标头添加到 common.h;没什么大不了的!
    • 我是否包含&lt;stdint.h&gt;&lt;cstdint&gt; 有关系吗?
    • @FrancisCugler &lt;cstdint&gt;.
    猜你喜欢
    • 2011-06-25
    • 1970-01-01
    • 2012-09-22
    • 2016-04-16
    • 2020-06-13
    • 2020-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多