这个警告与枚举类大小有关吗?

时间:2014-03-24 10:13:10

标签: c++ gcc c++11 enums

警告:

src/BoardRep.h:49:12: warning: ‘BoardRep::BoardRep::Row::<anonymous struct>::a’ 
is too small to hold all values of ‘enum class BoardRep::Piece’ 
[enabled by default]
Piece a:2;
        ^

枚举:

enum class Piece: unsigned char {
    EMPTY,
    WHITE,
    BLACK
};

使用:

union Row {
    struct {
        Piece a:2;
        Piece b:2;
        Piece c:2;
        Piece d:2;
        Piece e:2;
        Piece f:2;
        Piece g:2;
        Piece h:2;
    };
    unsigned short raw;
};

对于enum我同意GCC,它可能必须截断,但这是因为enum并不真正与整数和预处理器定义分开。但是enum class要强得多。如果它不够强大,不能假设作为整数的所有Piece值将在0和2之间(包括0和2),则警告是有意义的。否则海湾合作委员会不必要挑剔,可能值得邮寄清单说“看,这是一个愚蠢的警告”

任何人都看不到这一点

你可以在2位数据中存储4个不同的值,我只需要3个不同的值,所以任何长度为4或更小的枚举应该很好地适合给定的2位(我的枚举确实“派生”(更好的术语? )来自无符号类型)。如果我有5个或更多那么我会发出警告。

2 个答案:

答案 0 :(得分:9)

gcc发出的警告是准确的,没有必要向邮件列表撰写邮件,要求他们不太可能出现警告。

标准规定,基础类型unsigned char的枚举不能用长度为2的位域表示;即使没有具有这种价值的枚举。


标准

即使没有与此值对应的枚举键,枚举的基础值也是有效的,标准只表示要存储在枚举中的合法值必须适合基础类型;它没有说明枚举键中必须存在这样的值。

  

7.2 枚举声明 [dcl.enum]

     
    

7 ... 可以定义一个枚举,该枚举的值不是由任何枚举器定义的。 <子> ...

  


注意:引用的部分同时出现在C ++ 11和C ++ 14草案中。

注意:措辞陈述相同的内容,但使用不同的术语,可以在[dcl.enum]p6 下的C ++ 03中找到

注意:此帖子中未包含整个[decl.enum]p7以保留空间。


<强>详情

enum class E : unsigned char { A, B, C };

E x = static_cast<E> (10);

上面我们初始化x以存储值10,即使enum class E的枚举声明中没有枚举键,这仍然存在一个有效的结构。

考虑到上述情况,我们很容易推断10无法存储在长度为2的位字段中,因此gcc的警告只是准确的......我们是可能试图将值存储在我们无法表示的位域中。


示例

enum class E : unsigned char { A, B, C };

struct A {
  E value : 2;
};

A val;

val.value = static_cast<E> (10); // OMG, OPS!?

答案 1 :(得分:1)

根据C ++标准

  

8对于其基础类型是固定的枚举,其值为   枚举是基础类型的值。

因此,枚举值在

范围内
std::numeric_limits<unsigned char>::min() - std::numeric_limits<unsigned char>::max()

位字段a定义为

Piece a:2;

无法保存枚举的所有值。

如果要定义没有固定基础类型的无范围枚举,则其值的范围将为

0 - 2