为什么C编译器允许从uint16_t到枚举类型的静默强制转换?

为什么C编译器允许从uint16_t到枚举类型的静默强制转换?,c,enums,language-lawyer,C,Enums,Language Lawyer,我的印象是,将整数类型传递到需要枚举参数的函数中是一个错误,或者至少是一个警告。但是我用-Wall-Wextra-Werror试过了,没有警告。我错过了什么?C标准允许这样做吗 也许对我的直接使用来说更重要的是,是否有gcc或clang的编译器选项对此进行警告?将enum类型作为形式参数的目的是作为限制有效enum值的契约 #include <stdint.h> typedef enum { FLAG_A = 1, FLAG_B = 2, FLAG_C =

我的印象是,将整数类型传递到需要枚举参数的函数中是一个错误,或者至少是一个警告。但是我用
-Wall-Wextra-Werror
试过了,没有警告。我错过了什么?C标准允许这样做吗

也许对我的直接使用来说更重要的是,是否有gcc或clang的编译器选项对此进行警告?
enum
类型作为形式参数的目的是作为限制有效
enum
值的契约

#include <stdint.h>

typedef enum {
    FLAG_A = 1,
    FLAG_B = 2,
    FLAG_C = 4
} FLAG;

uint16_t flags = 0;

void clearFlags(FLAG flag)
{
    flags &= ~flag;
}

void doit()
{
    clearFlags(flags);   // this should not be ok; flags is type uint16_t
}
#包括
类型定义枚举{
标志A=1,
标志_B=2,
标志C=4
}旗帜;
uint16_t flags=0;
无效清除标志(标志)
{
旗子&=~旗子;
}
void doit()
{
clearFlags(flags);//这不应该是正常的;flags的类型是uint16\u t
}

枚举类型与整数类型兼容,因此将整数传递给需要
enum
作为参数的函数是有效的

有关枚举说明符的第6.7.2.2p4节规定:

每个枚举类型应与签名字符兼容 整数类型,或无符号整数类型。选择 类型由实现定义,但应能够
表示所有成员的值
枚举。枚举类型不完整,直到 紧接着终止枚举数列表的
}
声明,然后完成

兼容类型的定义见第6.2.7p1节:

如果两种类型的类型相同,则它们具有兼容的类型

这意味着一个枚举类型实际上与一个整数类型具有相同的类型。

这是合法的(如其他答案中所述)。编译器可能(但不是必须)警告:

为枚举类型的对象指定值,而不是通过分配作为该类型成员的枚举常量、具有相同类型的枚举对象或返回相同枚举类型的函数的值


-附件I,常见警告。

@ason S枚举在C中是整数类型。请阅读。我相信它在C11中是合法的(而不是在C++中)。仍然有一些编译器选择警告“混合枚举和整数”类型,哪些编译器?有没有办法在gcc或clang中打开该警告?与之相关(但不完全相同)!!!!即使传入的值不是
枚举中的有效值
@JasonS:Nothing限制
enum
s仅包含给定标签的值。事实上,通常使用
enum
列出标志掩码,期望实际值为一个或多个标记值的按位或。关键字“兼容”也是如此吗?C标准中“兼容”的含义是什么?@rici那么,如果一个单独的类型
enum MyEnum
的行为就像一个整数类型,那么它的意义是什么?如果我有一个函数
void doSomething(enum MyEnum e)
如果
e
可以是任何“兼容类型”的任意整数值,我为什么要麻烦呢?@jasonS:这是一个合理的问题,我没有答案。但是,那么,我也没有责任;40多年前设计C的不是我。你可以使用C++,它可以让你定义更接近你理想的EnUM类。我能说的是,这不是C的工作方式,大概从永远都是这样,现在不会改变。