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

Why does the C compiler allow silent casting from uint16_t to an enum type?

我的印象是将整数类型传递给需要枚举参数的函数是一个错误或至少是一个警告。但我在 Compiler Explorer-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
}

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

关于枚举说明符的 C standard 第 6.7.2.2p4 节指出:

Each enumerated type shall be compatible with char, a signed integer type, or an unsigned integer type. The choice of type is implementation-defined, but shall be capable of
representing the values of all the members of the
enumeration. The enumerated type is incomplete until immediately after the } that terminates the list of enumerator declarations, and complete thereafter.

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

Two types have compatible type if their types are the same.

所以这意味着枚举类型实际上与其中一种整数类型具有相同的类型。

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

A value is given to an object of an enumerated type other than by assignment of an enumeration constant that is a member of that type, or an enumeration object that has the same type, or the value of a function that returns the same enumerated type

— 附件一,常见警告