请参阅下面的简单示例.当一个函数返回一个enum
被分配给一个不同的变量enum
我甚至没有得到任何警告gcc -Wall -pedantic
.为什么C编译器不能对enum
s 进行类型检查?还是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();
}
Run Code Online (Sandbox Code Playgroud)
Kei*_*son 27
本声明:
enum fruit {
apple,
orange
};
Run Code Online (Sandbox Code Playgroud)
声明了三件事:一个叫做的类型enum fruit
,两个名为apple
and的枚举器orange
.
enum fruit
实际上是一种独特的类型.它与某些实现定义的整数类型兼容; 例如,只要所选择的类型可以表示所有值,就可以与实现选择的内容enum fruit
兼容int
,char
甚至使用unsigned long long
.
另一方面,枚举器是类型的常量int
.实际上,有一个常见的技巧是使用裸enum
声明来声明int
常量而不使用预处理器:
enum { MAX = 1000 };
Run Code Online (Sandbox Code Playgroud)
是的,这意味着常量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 */
/* ... */
}
Run Code Online (Sandbox Code Playgroud)
但结果是,正如您所见,如果您使用与一个枚举类型关联的常量,则编译器不太可能发出警告,而您的意思是使用不同的类型.
获得强类型检查的一种方法是将数据包装在结构中:
enum fruit { /* ... */ };
enum color { /* ... */ };
struct fruit { enum fruit f; };
struct color { enum color c; };
Run Code Online (Sandbox Code Playgroud)
struct fruit
并且struct color
是不同且不兼容的类型,它们之间没有隐式(或显式)转换.缺点是你必须明确地引用.f
或.c
成员.(大多数C程序员只是依靠他们在第一时间把事情做好的能力 - 结果好坏参半.)
(typedef
不提供强类型检查;尽管名称,它为现有类型创建别名,而不是新类型.)
(C++中的规则略有不同.)
可能我们大多数人都理解其根本原因("规范说它必须工作"),但我们也同意这是"C"领域中许多编程错误的原因,并且结构包装解决方法很严重.忽略像lint这样的附加检查器,这就是我们所拥有的:
gcc (4.9): No warning available.
microsoft cl (18.0): No warning available.
clang (3.5): YES -Wenum-conversion
Run Code Online (Sandbox Code Playgroud)