此警告是否与枚举类大小有关



警告:

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(,则该警告是有意义的。否则,GCC是不必要的挑剔,可能值得邮寄列表说"看,这是一个愚蠢的警告">

如果任何人都看不到这一点

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

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!?

根据C++标准

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

因此,您的枚举值在范围内

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

位字段a定义为

Piece a:2;

无法保存枚举的所有值。

如果您定义一个没有固定基础类型的无范围枚举,那么其值的范围将是

0 - 2

是的,此警告毫无意义,因为GCC已经警告将值分配给截断的位字段(枚举类型(:

warning: conversion from 'Some_Enum' to 'unsigned char:2'
         changes value from '(Some_Enum)9' to '1' [-Woverflow]

在警告的位置,只有所有声明的枚举器都可以保存在位字段中才相关。

在底层整数类型范围内的其他值(但与声明的枚举器不对应,btw通常定义良好(不能由字段表示的说法,如果被赋值,在技术上是正确的,但熵为零,这是一个警告。

因此,此警告在GCC 9.3中得到了修正。

IOW、GCC 9.3及更高版本不再警告此类代码。

相关内容

  • 没有找到相关文章

最新更新