枚举类型检查C / gcc

时间:2011-12-21 22:48:10

标签: c gcc enums

请参阅下面的简单示例。当将一个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();
}

6 个答案:

答案 0 :(得分:26)

此声明:

enum fruit {
    apple,
    orange
};

声明了三件事:一个名为enum fruit的类型,以及两个名为appleorange的枚举器。

enum fruit实际上是一种独特的类型。它与某些实现定义的整数类型兼容;例如,enum fruit可能与intchar兼容,如果实现选择,则可能与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 fruitstruct 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 longchar也不会发出警告shortlong

答案 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一起使用。