std :: bitset的并集成员的结构填充 [英] Structure padding with union members of std::bitset

查看:116
本文介绍了std :: bitset的并集成员的结构填充的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在将问题解决为此问题后,我继续扩展了此版本的代码以合并工会以前的模板版本与此版本中的数据字段的对应关系,到目前为止,我已经做到了:

After I had solved my issue to this question I went on to expand this version of my code to incorporate the unions of the data fields from my previous template versions with this version and I have this so far:

main.cpp

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

int main() {
    using namespace vpc;

    std::cout << std::boolalpha;

    std::cout << "std::bitset<64> is trivially copyable "
        << std::is_trivially_copyable<std::bitset<64>>::value << '\n'
        << "QWord is trivially copyable "
        << std::is_trivially_copyable<QWord>::value << '\n'
        << "DWord is trivially copyable "
        << std::is_trivially_copyable<DWord>::value << '\n'
        << "Word is trivially copyable "
        << std::is_trivially_copyable<Word>::value << '\n'
        << "Byte is trivially copyable "
        << std::is_trivially_copyable<Byte>::value << '\n'
        //      << "Bits is trivially copyable "
        //<< std::is_trivially_copyable<Bits>::value << '\n'
        << "My Register is trivially copyable "
        << std::is_trivially_copyable<Register>::value << "\n\n";


    std::cout << "sizeof(std::bitset<Byte>) = "  << sizeof(Byte)  << " bytes\n";
    std::cout << "sizeof(std::bitset<Word>) = "  << sizeof(Word)  << " bytes\n";
    std::cout << "sizeof(std::bitset<DWord>) = " << sizeof(DWord) << " bytes\n";
    std::cout << "sizeof(std::bitset<QWord>) = " << sizeof(QWord) << " bytes\n";
    std::cout << "sizeof(Register) = "      << sizeof(Register) << " bytes\n\n";

    Register r;

    std::cout << "sizeof(Register::byte) = " << sizeof(r.byte)  << " bytes\n";
    std::cout << "sizeof(Register::Byte) = " << sizeof(r.byte) / sizeof(r.byte[0]) << " bytes\n";

    std::cout << "sizeof(Register::word) = " << sizeof(r.word)  << " bytes\n";
    std::cout << "sizeof(Register::Word) = " << sizeof(r.word) / sizeof(r.word[0]) << " bytes\n";

    std::cout << "sizeof(Register::dword) = " << sizeof(r.dword) << " bytes\n";
    std::cout << "sizeof(Register::DWord) = " << sizeof(r.dword) / sizeof(r.dword[0]) << " bytes\n";

    std::cout << "sizeof(Register::value) = " << sizeof(r.value) << " bytes\n";

    std::cout << "sizeof(Register) = " << sizeof(r) << " bytes\n\n";

    r.value = 0xFFFFFFFFFFFFFFFF;
    std::cout << "value = " << r.value.to_ullong() << '\n' << r.value << '\n';
    for (std::uint16_t i = 0; i < 8; i++) {
        std::cout << "byte_" << i << " : " << r.byte[i] << '\n';
    }

    return EXIT_SUCCESS;
}

注册.h

#pragma once

#include <algorithm>
#include <bitset>
#include <string>
#include <vector> // include for typedefs below.

namespace vpc {
    typedef std::int8_t  i8;
    typedef std::int16_t i16;
    typedef std::int32_t i32;
    typedef std::int64_t i64;

    const std::uint16_t BYTE = 0x08;
    const std::uint16_t WORD = 0x10;
    const std::uint16_t DWORD = 0x20;
    const std::uint16_t QWORD = 0x40;

    typedef std::bitset<BYTE>  Byte;
    typedef std::bitset<WORD>  Word;
    typedef std::bitset<DWORD> DWord;
    typedef std::bitset<QWORD> QWord;

    struct Register {

        union {
            QWord value{ 0 };

            union {
                DWord dword[2];
                struct {
                    DWord dword0;
                    DWord dword1;
                };
            };

            union {
                Word word[4];
                struct {
                    Word word0;
                    Word word1;
                    Word word2;
                    Word word3;
                };
            };

            union {
                Byte byte[8];
                struct {
                    Byte byte0;
                    Byte byte1;
                    Byte byte2;
                    Byte byte3;
                    Byte byte4;
                    Byte byte5;
                    Byte byte6;
                    Byte byte7;
                };
            };
        };

        Register() : value{ 0 } {}
    };

    Register reverseBitOrder(Register& reg, bool copy = false);

} // namespace vpc

Register.cpp

#include "Register.h"

namespace vpc {

    Register reverseBitOrder(Register& reg, bool copy) {
        auto str = reg.value.to_string();
        std::reverse(str.begin(), str.end());

        if (copy) { // return a copy
            Register cpy;
            cpy.value = QWord(str);
            return cpy;
        }
        else {
            reg.value = QWord(str);
            return {};
        }
    }

} // namespace vpc

输出

std::bitset<64> is trivially copyable true
QWord is trivially copyable true
DWord is trivially copyable true
Word is trivially copyable true
Byte is trivially copyable true
My Register is trivially copyable true

sizeof(std::bitset<Byte>) = 4 bytes
sizeof(std::bitset<Word>) = 4 bytes
sizeof(std::bitset<DWord>) = 4 bytes
sizeof(std::bitset<QWord>) = 8 bytes
sizeof(Register) = 32 bytes

sizeof(Register::byte) = 16 bytes
sizeof(Register::Byte) = 4 bytes
sizeof(Register::word) = 16 bytes
sizeof(Register::Word) = 4 bytes
sizeof(Register::dword) = 8 bytes
sizeof(Register::DWord) = 2 bytes
sizeof(Register::value) = 8 bytes
sizeof(Register) = 32 bytes

value = 18446744073709551615
1111111111111111111111111111111111111111111111111111111111111111
byte_0 : 11111111
byte_1 : 11111111
byte_2 : 11001100
byte_3 : 11001100
byte_4 : 11001100
byte_5 : 11001100
byte_6 : 11001100
byte_7 : 11001100

在查看了打印出的数据后,找到了bitset类型的大小,然后将它们与作为联合中的结构成员的它们的实际大小进行了比较.我正在尝试弄清这里到底发生了什么.

After looking at the printed out data for the sizes of the bitset types then comparing them to the actual sizes of them as members of a struct within in a union. I'm trying to figure out what's going on under the hood here.

我不确定我是否正确执行sizeof计算,是否与bitset的内部存储有关?我试图了解作为成员的并集上下文中的数据对齐方式基本类型是std::bitset类型的结构的名称.从标题中您可以看到它们有4种变体:bitset<8> = Bytebitset<16> = Wordbitset<32> = DWord& bitset<64> = QWord

I'm not sure if I'm performing the sizeof calculations correctly of if it has to do with the internal storage of bitset I'm trying to get a grasp on the data alignment within the context of unions as members of a structure where the underlying type is that of std::bitset types. From the header you can see that there are 4 variations of these: bitset<8> = Byte, bitset<16> = Word, bitset<32> = DWord & bitset<64> = QWord

从本质上讲,应该对它们进行可分割的映射:

In essences there should be a divisible mapping of these:

// each [] = 1 byte or 8 bits for simplicity
bitset<64> = [] [] [] [] [] [] [] []
bitset<32> = [] [] [] []
bitset<16> = [] []
bitset<8>  = []

因此,当我尝试像这样在联合体中使用它们时:

So when I try to use them in a union as such:

union {
    QWord q;

    union {
        DWord d[2];
        struct {
            DWord d_0;
            DWord d_1;
        };
    };

    union {
        Word w[4];
        struct {
            Word w_0;
            Word w_1;
            Word w_2;
            Word w_3;
         };
    };

    union {
        Byte b[8];
        struct {
            Byte b_0;
            Byte b_1;
            Byte b_2;
            Byte b_3;
            Byte b_4;
            Byte b_5;
            Byte b_6;
            Byte b_7; 
        };
    };
};

我认为通过使用在联合上方显示的模式,我可以将数据打包为字节大小对齐方式:

I would think that by using the pattern that I shown above this union that I would be able to pack the data into byte size alignments:

// each inner [] = 1 byte or 8 bits
// and each outer [] = index into array

         0   1   2   3   4   5   6   7
value = [ ] [ ] [ ] [ ] [ ] [ ] [ ] [ ]

                 0               1
dword[2] = [[] [] [] []],  [[] [] [] []]

             0        1        2        3
word[4] = [[] []], [[] []], [[] []], [[] []] 

             0     1     2     3     4     5     6     7
byte[8]  = [[ ]] [[ ]] [[ ]] [[ ]] [[ ]] [[ ]] [[ ]] [[ ]]

但是,这似乎并没有像我期望的那样发生.

However this doesn't seem to be happening as I would expect.

我的总体目标是模拟上面所表达的模式,从而使寄存器的基本大小为64位或8字节宽,并且通过使用并集,我将能够从中访问子字节,字或dword.完整的qword.

My overall goal is to simulate the pattern above that I had expressed so that the basic size of a Register is 64 bits or 8 bytes wide and through the use of unions I would be able to access sub bytes, word or dwords from the full qword.

请您能详细说明我在这里缺少的内容吗?我不确定std::bitset是否与内存中的存储方式有关,是否与结构对齐有关,还是与工会本身打交道,我不确定.

Would you please be able to elaborate on what I'm missing here? I'm not sure if it has to do with how std::bitset is stored in memory, if it has to do with a structures alignment or if it has to deal with unions themselves.

推荐答案

您想要的内容无法以您想要的方式完成. std::bitset不能保证其大小,因此不能期望bitset<8>具有一个字节的大小.如果这些bitset的成员不是活动的联合成员,则您也无法访问它们.

What you want cannot be done in the way that you want to do it. std::bitset makes no guarantees about its size, so there's no expectation that a bitset<8> will have the size of a byte. Nor is there any way for you to access the members of these bitsets if they are not the active union member.

您要执行的操作是:

  1. 存储uint64_t.
  2. 通过范围兼容的对象访问该uint64_t位的各个子集.
  1. Store a uint64_t.
  2. Access various subsets of the bits of that uint64_t through a range-compatible object that allows you to manipulate them.

所以只需实现那个.您所需要的不是bitset,而是位范围视图类型,它允许您将uint64_t中的任何连续位序列解释和操纵为一个范围.基本上,您想要的是bitset的接口,但是要通过引用存储(以及该存储的特定范围)来实现,而不是通过成为.您不存储这些范围;您可以根据要求生成范围.

So just implement that. What you need is not bitset, but a bit-range view type, one that allows you to interpret and manipulate any contiguous sequence of bits in that uint64_t as a range. Basically, you want the interface of bitset, but through a reference to the storage (and a particular range of that storage), not by being the storage. You don't store these ranges; you generate ranges upon request.

这篇关于std :: bitset的并集成员的结构填充的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆