当我运行下面的代码时-我得到警告"在{}内从int到long unsigned int的转换变窄在C ++ 11中是错误的[-Wnarrowing]。我正在使用GNU 4.8编译器。
typedef struct TableEntry
{
unsigned long value;
const char *label;
} TableEntry;
enum FunctionType
{
NORMAL = 0,
RANGE = 1
};
TableEntry functionTypes[] =
{
{NORMAL, "NORMAL"},
{RANGE,"RANGE"}
};
我不明白为什么编译器将枚举视为int?
这是GCC 4.8中的错误吗? 有什么解决方法吗?
任何帮助表示赞赏。
我相信枚举始终被视为int的幕后花絮。如果您不指定枚举值的值,则它们的默认值为0、1、2,...。在这种情况下,您应该可以进行隐式转换,因为转换不会花费任何准确性。
我们在每个文件中都有这些警告。约150个文件。我的老板不喜欢看到警告。
这是有效的C ++ 03代码,因此g ++警告很可能是没有根据的。如果C ++ 11标准破坏了C ++ 03代码批发,的确会引起注意。也就是说,这只是不对数字值使用无符号整数的另一个原因。
只要您确定隐式转换不会给您带来任何问题,就可以暂时禁用该警告。但是我真的不建议您使用长期解决方案,因为启用该警告可能会在其他数据转换方案中省去您的头痛。
枚举FunctionType:无符号长{/ *等* /};这是向后进行的操作,请改而修复struct声明。
如果可行,请执行以下操作:
enum FunctionType
{
NORMAL = 0,
RANGE = 1
};
typedef struct TableEntry
{
FunctionType value;
const char *label;
} TableEntry;
TableEntry functionTypes[] =
{
{NORMAL, "NORMAL"},
{RANGE,"RANGE"}
};
否则,将结构中的类型更改为int,或将枚举显式基于与该结构中相同的类型。
顺便说一句,我认为g ++警告是没有根据的和错误的,因为原始代码是有效的C ++ 03。在C ++ 11中。我简直不敢相信。
关于命名约定:所有大写标识符对于Java程序员(习惯了该约定)都是有用的,但是在C ++中,它们增加了无意替换文本的机会。还有美学方面的考虑。在为宏保留所有大写字母方面大有裨益。
您能否指出信息来源,认为这是c ++ 11中的重大变化?
@戴夫:问题中的代码就是一个例子。可以使用C ++ 03,不能使用C ++ 11。那就是"破坏"的意思,它破坏了现有的代码。
通常,无作用域枚举的基础类型为int(它可以是可以表示枚举器所有值的任何整数类型)。
但是我看不到任何缩小的转换,因为unsigned long类型可以表示int类型的所有值。
编辑:似乎我错了,因为我在标准中找到了一个与我的假设相矛盾的例子
unsigned int ui1 = {-1}; // error: narrows
因此,无法使用包含负数的初始化列表初始化unsigned int。
因此,为了避免警告,枚举可以写为
enum FunctionType : unsigned int // or unsigned long
{
NORMAL = 0,
RANGE = 1
};
int可以取负值,而unsigned long则不能。因此缩小了转化率
int值的大约一半不能表示为unsigned long。
@srinivas所有int类型的值(包括负数)都可以用unsigned long类型表示。类型unsigned long是int和unsigned long的通用类型。
@干杯和hth。 -Alf据我所知,标准的所有int值(包括负数)都可以用unsigned long类型表示。
@干杯和hth。 -Alf看来你是对的。我安排了我的职位。
@srinivas看来你是对的。我更新了我的帖子。
您可以将"值"更改为int
或者,您可以使用强类型的新"枚举类"(c ++ 11),然后将您的"值"声明为这种类型。
感谢您的建议。我在大约150个文件中收到了这些警告。有没有更好的方法呢?
有趣的是,我的前两个建议是:将value的类型更改为FunctionType,或使FunctionType得到unsigned long的支持。
由于您使用的是c ++ 11,因此可以这样声明您的枚举:
enum Enum2 : unsigned char;
那应该迫使枚举起作用。就是说,IDEONE对您发布的代码没有警告/错误。可能只是GCC过于腐。