c++ - 在结构和模板中试验 union 和位域

标签 c++ templates struct unions bit-fields

为了更好地处理和理解位域、 union 和结构的字节对齐如何工作,我模拟了一个模板寄存器结构。

我的注册要求如下:

  • 寄存器的默认大小或宽度为 8 位或 1 个字节
  • 较大的寄存器必须是 8 的倍数
  • 寄存器的大小小于或等于 64 位或 8 个字节。

我有一组结构,从 Byte 的基本单位到 QWord,它们以级联效应相互构建。

我的寄存器是模板特化。

到目前为止,这是我的代码:

-main.cpp-

#include <iostream>
#include "Register.h"

int main() {
    Register r1;
    r1.value.value_ = 8;

    Register<16> r2;
    r2.value.value_ = 16;

    Register<32> r3;
    r3.value.value_ = 32;

    Register<64> r4;
    r4.value.value_ = 64;

    std::cout << static_cast<std::uint8_t>( r1.value.value_) << "\n";
    std::cout << static_cast<std::uint16_t>(r2.value.value_) << "\n";
    std::cout << static_cast<std::uint32_t>(r3.value.value_) << "\n";
    std::cout << static_cast<std::uint64_t>(r4.value.value_) << "\n";

    return EXIT_SUCCESS;
}

-Register.h-

#pragma once

#include <vector> // include for typedefs below.
typedef std::int8_t  i8;
typedef std::int16_t i16;
typedef std::int32_t i32;
typedef std::int64_t i64;

struct MyByte {
    union {
        i8 value_;
        struct {
            i8 b0 : 1;
            i8 b1 : 1;
            i8 b2 : 1;
            i8 b3 : 1;
            i8 b4 : 1;
            i8 b5 : 1;
            i8 b6 : 1;
            i8 b7 : 1;
        };
    };
};

struct MyWord {        // same as short or i16  
    union {
        i16 value_;
        union {
            MyByte byte_[2];
            struct {
                MyByte b0_;
                MyByte b1_;
            };
        };
    };
};

struct MyDWord {       // same as int or i32
    union {
        i32 value_;

        struct {
            MyWord w0_;
            MyWord w1_;
        };

        union {
            MyByte byte_[4];
            struct {
                MyByte b0_;
                MyByte b1_;
                MyByte b2_;
                MyByte b3_;
            };
        };
    };
};

struct MyQWord {     // same as long or i64
    union {
        i64 value_;
        struct {
            MyDWord d0_;
            MyDWord d1_;
        };
        struct {
            MyWord w0_;
            MyWord w1_;
            MyWord w2_;
            MyWord w3_;
        };
        union { 
            MyByte byte_[8];
            struct {
                MyByte b0_;
                MyByte b1_;
                MyByte b2_;
                MyByte b3_;
                MyByte b4_;
                MyByte b5_;
                MyByte b6_;
                MyByte b7_;
            };
        };
    };
};

template<size_t N = 8>
struct Register {
    MyByte value;
    Register() {
        static_assert(
         ((N % 8) == 0) &&
         (N >= 8) &&
         (N <= 64)

        );
    }
};

template<>
struct Register<16> {
    MyWord value;
    Register() = default;
};

template<>
struct Register<32> {
    MyDWord value;
    Register() = default;
};

template<>
struct Register<64> {
    MyQWord value;
    Register() = default;
};

上述代码在 Visual Studio 2017 中编译、运行并退出,代码为 0,编译器设置为最新的草案标准。

既然您已经看过代码,我在一定程度上理解了位域和 union ,但是当我不经常使用它们时,它们可能会让我有点困惑。我确实知道,当以组合方式使用它们时,它会导致代码不可移植,尤其是在不同的编译器、操作系统和体系结构 (endian) 之间。

然而,这只是实验代码,可以作为很好的复习练习。

我在这里遇到的问题是我的输出。所有的高阶寄存器似乎都工作正常,我只测试过直接通过最里面的成员变量 value_ 获取它。但是,我从默认或最基本的寄存器(8 位大小的寄存器)中获取结果。将值设置为当前值。我得到这个作为输出:

--

16
32
64

如果我将 main 更改为:

#include <iostream>
#include "Register.h"

int main() {
    Register r;
    for (i8 i = 0; i < 21; i++) {
        1.value.value_ = i;
        std::cout << static_cast<std::uint8_t>(r.value.value_) << "\n";
    }
    return EXIT_SUCCESS;
}

我得到的这个输出在混合的某个地方发出哔哔声:

☺
☻
♥
♦
♣
♠





♂
♀

♫
☼
►
◄
↕
‼
¶

这是否与 std::int8_t 的定义有关?它是基于 char 值类型而不是 int 类型吗?它仍然应该是完整的......如果是这种情况,它是否必须处理 union 或位域等中的无符号值?是什么导致 ASCII 符号打印到控制台。

最佳答案

Is it based on a char value type instead of a int type?

char *是*一个整数类型。该标准允许 std::int8_t 成为 char 的类型定义。

std::cout << static_cast<std::uint64_t>(r.value.value_) << "\n";

嗯。

关于c++ - 在结构和模板中试验 union 和位域,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55988878/

相关文章:

c++ - labeled_graph 中的权重

struct - 选项类型是否小于包装类型加上 boolean 值?

基于模板的派生类和可变参数的 C++ 构造函数

c++ - 模板 lambda 与带有模板 operator() 的仿函数

c++ - 使类模板化强制在继承构造函数中重复基类模板参数

c++ - 如何在C++中实现不同列数据类型的数据表

c++ - 当函数是指向类函数的指针但在该类之外时如何正确调用函数

c - 这种排序方法是如何工作的?

c++ - 在 VS2010 中使用 list_of 调用不明确

c++ - CWinThread 被 AfxBeginThread 创建后谁拥有它?