简体   繁体   中英

Creating constructor for a struct(union) in C++

What is the best way to create a constructor for a struct(which has a union member, does it matter?) to convert uint8_t type into the struct?

Here is my example to clarify more:

struct twoSixByte
{
    union {
        uint8_t fullByte;
        struct
        {
            uint8_t twoPart : 2;
            uint8_t sixPart : 6;
        } bits;
    };
};

uint32_t extractByte(twoSixByte mixedByte){
  return mixedByte.bits.twoPart * mixedByte.bits.sixPart;
}

uint8_t tnum = 182;
print(extractByte(tnum)); // must print 2 * 54 = 108

PS Finding from comments & answers, type-punning for unions is not possible in C++.

The solutions given are a little bit complicated specially where there are lots of these structures in the code. There are even situations where a byte is divided into multiple bit parts(more than two). So without taking advantage of unions and instead using bitsets ans shifting bits adds a lot of burden to the code.

Instead, I managed for a much simpler solution. I just converted the type before passing it to the function. Here is the fixed code:

struct twoSixByte
    {
        union {
            uint8_t fullByte;
            struct
            {
                uint8_t twoPart : 2;
                uint8_t sixPart : 6;
            } bits;
        };
    };

    uint32_t extractByte(twoSixByte mixedByte){
      return mixedByte.bits.twoPart * mixedByte.bits.sixPart;
    }

    uint8_t tnum = 182;
    twoSixByte mixedType;
    mixedType.fullByte = tnum;
    print(extractByte(mixedByte)); // must print 2 * 54 = 108

Unless there is a pressing need for you to use a union , don't use it. Simplify your class to:

struct twoSixByte
{
   twoSixByte(uint8_t in) : twoPart((in & 0xC0) >> 6), sixPart(in & 0x3F) {}
   uint8_t twoPart : 2;
   uint8_t sixPart : 6;
};

If there is a need to get the full byte, you can use:

uint8_t fullByte(twoSixByte mixedByte)
{
   return ((mixedByte.twoPart << 6) | mixedByte.sixPart);
}

You could avoid the union and type punning and use a struct with the relevant member function. Note that we don't need a constructor if the struct is regarded as an aggregate to be initialized :

#include <cstdint>

struct twoSixByte {
    uint8_t fullByte; // no constructor needed, initializing as an aggregate
    uint32_t extractByte(){
        return ((fullByte & 0b1100'0000) >> 6) * (fullByte & 0b0011'1111);
    }
};


int main()
{
    twoSixByte tnum{182};
    auto test = tnum.extractByte(); // test == 2 * 54 == 108
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM