请参阅下面的简单示例。当将一个enum
返回的函数分配给另一个enum
的变量时,即使使用gcc -Wall -pedantic
,我也不会收到任何警告。为什么C编译器不能对enum
进行类型检查?或者它是gcc
具体的吗?我现在无法访问任何其他编译器来试用它..
enum fruit {
APPLE,
ORANGE
};
enum color {
RED,
GREEN
};
static inline enum color get_color() {
return RED;
}
int main() {
enum fruit ftype;
ftype = get_color();
}
答案 0 :(得分:26)
此声明:
enum fruit {
apple,
orange
};
声明了三件事:一个名为enum fruit
的类型,以及两个名为apple
和orange
的枚举器。
enum fruit
实际上是一种独特的类型。它与某些实现定义的整数类型兼容;例如,enum fruit
可能与int
,char
兼容,如果实现选择,则可能与unsigned long long
兼容,只要所选类型可以表示所有值。
另一方面,枚举数是int
类型的常量。实际上,使用裸enum
声明来声明int
常量而不使用预处理器是一种常见的技巧:
enum { MAX = 1000 };
是的,这意味着常量apple
,即使它被声明为enum fruit
定义的一部分,但实际上并不是enum fruit
类型。其原因是历史性的。是的,对于枚举器而言,它可能更有意义是该类型的常量。
在实践中,这种不一致性很少发生。在大多数情况下,离散类型(即整数和枚举类型)在很大程度上是可互换的,隐式转换通常是正确的。
enum fruit { apple, orange };
enum fruit obj; /* obj is of type enum fruit */
obj = orange; /* orange is of type int; it's
implicitly converted to enum fruit */
if (obj == orange) { /* operands are converted to a common type */
/* ... */
}
但结果是,正如您所见,如果您使用与一个枚举类型关联的常量,当您打算使用不同的常量时,编译器不太可能发出警告。
获得强类型检查的一种方法是将数据包装在结构中:
enum fruit { /* ... */ };
enum color { /* ... */ };
struct fruit { enum fruit f; };
struct color { enum color c; };
struct fruit
和struct color
是不同且不兼容的类型,它们之间没有隐式(或显式)转换。缺点是您必须明确地引用.f
或.c
成员。 (大多数C程序员只是依靠他们在第一时间把事情做好的能力 - 结果好坏参与。)
(typedef
没有为您提供强类型检查;尽管有名称,但它会为现有类型创建别名,而不是新类型。)
(C ++中的规则略有不同。)
答案 1 :(得分:5)
可能我们大多数人都了解其根本原因(“规范说它必须有效”),但我们也同意这是导致“C”地区出现大量编程错误的原因,并且结构包装解决方法是粗略的。忽略像lint这样的附加检查器,这就是我们所拥有的:
gcc (4.9): No warning available.
microsoft cl (18.0): No warning available.
clang (3.5): YES -Wenum-conversion
答案 2 :(得分:3)
gcc
决定不发出警告(clang
),但icc
(英特尔编译器)会在这种情况下发出警告。如果您想要对enum
类型进行其他类型检查,可以将代码传递给某些静态代码检查软件,例如Lint
,以便在这种情况下发出警告。
gcc
认为警告enum
类型之间的隐式转换没有用,但另请注意,在两个不同的{{{}}之间进行赋值时,C不要求实现发出诊断。 1}}类型。这与任何算术类型之间的分配相同:C不需要诊断。例如,如果您将enum
分配给gcc
或者long long
,char
也不会发出警告short
到long
。
答案 3 :(得分:2)
这是因为C中的enum
只是一组唯一的整数常量,这使您不必拥有#define
一大堆常量。它不像C ++,你创建的enum
是特定类型的。 这就是C的方式。
值得注意的是,用于表示enum
值的实际大小取决于编译器。
答案 4 :(得分:1)
C中的枚举基本上像整数一样处理。这是使用常量的更好方法。
// this would work as well
ftype = 1;
您还可以指定值:
enum color {
RED=0,GREEN,BLUE
} mycolor;
mycolor = 1; // GREEN
答案 5 :(得分:0)
gcc家伙总是有理由不做某事。
将clang与选项-Wenum-conversion -Wassign-enum
一起使用。