mrantifreeze
mrantifreeze

Reputation: 65

Define an enum to be smaller than one byte / Why is this struct larger than one byte?

I'd like to define an enum to be smaller than one byte while maintaining type safety.

Defining an enum as:

enum MyEnum : unsigned char
{
    i ,j, k, w
};

I can shrink it to one byte, however I'd like to make it use only 2 bits since I will at most have 4 values in it. Can this be done?

In my struct where I use the enum, the following does not work

struct MyStruct
{
    MyEnum mEnum : 2; // This will be 4 bytes in size
};

Thanks!

Update:

The questions comes from this scenario:

enum MyEnum : unsigned char
{
    i ,j, k, w
};

struct MyStruct
{
    union
    {
        signed int mXa:3;
        unsigned int mXb:3;
    };

    union
    {
        signed int mYa:3;
        unsigned int mYb:3;
    };

    MyEnum mEnum:2;
};

sizeof(MyStruct) is showing 9 bytes. Ideally I'd like the struct to be 1 bytes in size.

Update for implemented solution:

This struct is one byte and offers the same functionality and type safety:

enum MyEnum :unsigned char
{
   i,j,k,w
};

struct MyStruct
{
   union
   {
      struct { MyEnum mEnum:2; char mXa:3; char mXb:3;};
      struct { MyEnum mEnum:2; unsigned char mYa:3; unsigned char mYb:3;};
   }; 
};

Upvotes: 3

Views: 4961

Answers (4)

PlasmaHH
PlasmaHH

Reputation: 16046

As per standard definition, a types sizeof must be at least 1 byte. This is the smallest addressable unit of memory.

The feature of bitfields you are mentioning allows to define members of structures to have smaller sizes, but the struct itself may not be because

  • It must be of at least 1 byte too
  • Alignment considerations might need it to be even bigger

additionally you may not take the address of bitfield members, since as said above, a byte is the smallest addressable unit of memory (You can already see that by sizeofactually returning the number of bytes, not bits, so if you expected less than CHAR_BIT bits, sizeof would not even be able to express it).

Upvotes: 5

Mooing Duck
Mooing Duck

Reputation: 66961

bitfields can only share space if they use the same underlying type. And any unused bits are actually left unused; if the sum of bits in an unsigned int bitfield is 3 bits, it still takes 4 bytes total. Since both enums have unsigned int members, they're both 4 bytes, but since they are bitfields, they have an alignment of one. So the first enum is 4 bytes, and the second is four bytes, then the MyEnum is 1 byte. Since all of those have an alignment of one, no padding is needed.

Unfortunately, union doesn't really work with bitfields really at all. Bitfields are for integer types only. The most I could get your data to without serious redesign is 3 bytes: http://coliru.stacked-crooked.com/view?id=c6ad03c93d7893ca2095fabc7f72ca48-e54ee7a04e4b807da0930236d4cc94dc

enum MyEnum : unsigned char
{
    i ,j, k, w
};

union MyUnion
{
    signed char ma:3; //char to save memory
    unsigned char mb:3;
};

struct MyStruct
{
    MyUnion X;
    MyUnion Y; 
    MyEnum mEnum;
}; //this structure is three bytes

In the complete redesign category, you have this: http://coliru.stacked-crooked.com/view?id=58269eef03981e5c219bf86167972906-e54ee7a04e4b807da0930236d4cc94dc

Upvotes: 1

Mike Vine
Mike Vine

Reputation: 9837

Bit packing 'Works for me'

#include <iostream>

enum MyEnum : unsigned char
{
    i ,j, k, w
};
struct MyStruct
{
    MyEnum mEnum : 2;
    unsigned char val : 6;
};

int main()
{
    std::cout << sizeof(MyStruct);
}

prints out 1. How / what are you measuring?

Edit: Live link

Are you doing something like having a pointer as the next thing in the struct? In which case, you'll have 30bits of dead space as pointers must be 4 byte aligned on most 32bit systems.

Edit: With your updated example, its the unions which are breaking you

enum MyEnum : unsigned char
{
    i ,j, k, w
};


struct MyStruct
{
    unsigned char mXb:3;
    unsigned char mYb:3;

    MyEnum mEnum:2;
};

Has size 1. I'm not sure how unions and bit packing work together though, so I'm no more help.

Upvotes: 0

Fred Larson
Fred Larson

Reputation: 62103

No. C++ defines "char" to be the smallest addressable unit of memory for the platform. You can't address 2 bits.

Upvotes: 1

Related Questions