将枚举定义为小于一个字节/为什么此结构大于一个字节?

时间:2013-06-11 20:56:47

标签: c++ optimization enums standards

我想在保持类型安全的同时将枚举定义为小于一个字节。

将枚举定义为:

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

我可以把它缩小到一个字节,但是我想让它只使用2位,因为我最多只有4个值。可以这样做吗?

在我使用枚举的结构中,以下内容不起作用

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

谢谢!

更新

问题来自这种情况:

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)显示9个字节。理想情况下,我希望结构的大小为1个字节。

已实施解决方案的更新:

此结构是一个字节,提供相同的功能和类型安全性:

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;};
   }; 
};

4 个答案:

答案 0 :(得分:4)

根据标准定义,类型sizeof必须至少为1个字节。这是最小的可寻址内存单元。

您提到的位域的功能允许定义结构的成员以具有更小的尺寸,但结构本身可能不是因为

  • 它必须至少为1个字节
  • 对齐注意事项可能需要它更大

另外你可能不会获取位域成员的地址,因为如上所述,一个字节是内存的最小可寻址单位(你已经可以看到sizeof实际上返回的是字节数,而不是位数,因此,如果您预计会少于CHAR_BIT位,sizeof甚至无法表达它。)

答案 1 :(得分:1)

没有。 C ++将“char”定义为平台的最小可寻址内存单元。你不能解决2位。

答案 2 :(得分:1)

位域只有在使用相同的底层类型时才能共享空间。任何未使用的位实际上都是未使用的;如果unsigned int位域中的位总和为3位,则仍需要4个字节 total 。由于两个枚举都有unsigned int个成员,因此它们都是4个字节,但由于它们是位域,因此它们的对齐方式为1。所以第一个enum是4个字节,第二个是4个字节,那么MyEnum是1个字节。由于所有这些都具有一个对齐,因此不需要填充。

不幸的是,union根本不适用于位域。位域仅适用于整数类型。在没有认真重新设计的情况下,我能获得的最多数据是3个字节: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

在完整的重新设计类别中,您有:http://coliru.stacked-crooked.com/view?id=58269eef03981e5c219bf86167972906-e54ee7a04e4b807da0930236d4cc94dc

答案 3 :(得分:0)

比特包装'适合我'

#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);
}

打印出来1.你是如何/你在测量什么?

修改:Live link

你是否正在做一个像指针作为结构中的下一个东西?在这种情况下,你将有30位死区,因为指针必须在大多数32位系统上对齐4字节。

编辑:使用您更新的示例,其中的工会正在破坏您

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


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

    MyEnum mEnum:2;
};

大小1.我不确定工会和比特包装是如何协同工作的,所以我没有更多的帮助。