【问题标题】:Enum in C is not throwing an error on invalid inputC中的枚举不会在无效输入上引发错误
【发布时间】:2014-02-10 16:56:34
【问题描述】:

我正在使用 gcc,我编译了这段代码,它应该会抛出错误,但它运行成功。

enum DIRECTION {EAST,WEST,NORTH,SOUTH};

int main(void) {
    enum DIRECTION currentDirection = 10;
    printf("%d\n",currentDirection);
    return 0;
}

输出: 10

【问题讨论】:

  • 为什么你认为它应该抛出错误?
  • 据我所知,枚举不允许任何其他值。
  • C 的类型没有你希望的那么强...
  • 你的枚举只是一个“int”。因此,您可以分配一个超出范围的数字
  • 当您使用 class 关键字定义 enum 时,在 C++ 中也是如此。

标签: c enums


【解决方案1】:

枚举类型在C99 draft standard 部分6.7.2.2 枚举说明符中定义为:

每个枚举类型都应与 char、有符号整数类型或 无符号整数类型。类型的选择是实现定义的,110) [...]

脚注110 说:

实现可能会延迟选择哪种整数类型,直到看到所有枚举常量。

标准并没有说您不能指定枚举声明中指定的值之外的值,尽管在 Annex I Common warnings 部分中确实提出了这样的警告,但它是不需要:

一个值被赋予一个枚举类型的对象,而不是通过赋值 作为该类型成员的枚举常量,或具有 相同的类型,或返回相同枚举类型的函数的值(6.7.2.2)。

gcc 不会产生警告,尽管带有-Wassign-enum 标志或-Weverything 标志的clang 会产生警告,并且看起来类似于:

警告:整数常量不在枚举类型 'enum DIRECTION' [-Wassign-enum] 的范围内

您可以使用-Werror 使其成为错误。

Keith 提出了两个有趣的观察结果:

  • 使用-Werror 会使clang 不一致,因为代码是有效的C
  • enum DIRECTION currentDirection = 128; 具有实现定义的行为,因为类型很可能是 char

【讨论】:

  • 请注意,使用-Werror 会使 gcc 不一致。问题中的代码是严格符合的(一旦添加了所需的#include <stdio.h>),符合要求的编译器可能不会拒绝它(除非它违反了一些奇怪的容量限制)。
  • 另一个有趣的花絮:enum DIRECTION currentDirection = 10; 是有效的,但enum DIRECTION currentDirection = 128; 具有实现定义的行为。
  • @KeithThompson 很有趣,我明白你在说什么。
【解决方案2】:

在 C 中,枚举常量等价于 int。您可以互换使用它们。

【讨论】:

  • 一个enum 类型是一个独特的类型,兼容一些实现定义的整数类型(不一定是int)。另一方面,枚举常量的类型为int
  • 这并不能真正回答问题。问题中的代码使用int 常量来初始化enum DIRECTION 对象。枚举常量EAST 等都是int 类型的事实并不直接相关,因为代码不使用任何枚举器。相关的是 enum 类型实际上是实现定义的整数类型,使用 int 常量初始化这样的对象涉及隐式转换。
  • 从其他语言规则可以推断出enum DIRECTION兼容的整数类型的最大值,其宽度足以代表10的值。
【解决方案3】:

enum(枚举)是一种可以保存一组由用户指定的整数值的类型。这是一种为一小部分相关值创建符号名称的方法。它们的目的是使程序更清晰、更易读。

enum 类型的值称为枚举器。枚举数与enum 在同一范围内,并且它们的值隐式转换为整数。

宏用于预处理器,编译后的代码不知道您创建的宏。在代码到达编译器之前,它们已经被预处理器替换。枚举是编译时实体,编译后的代码保留有关符号的完整信息,这些信息在调试器(和其他工具)中可用。

以后添加一个新的符号名称并让值自己重新排序也很方便。但是C 中的enums 不是强类型的,并且与有符号整数兼容。因此,您可以为 enum 类型变量分配任何值。

// APPLE == 0, PEARS == 1, ...

enum fruits {APPLE, PEARS, BANANA};

// APPLE == 0, MANGO == 1, PEARS == 2, ...

enum fruits {APPLE, MANGO, PEARS, BANANA};
enum color {APPLE, PEACH};

enum color my_color = MANGO;  // not strongly typed
enum fruits my_fruit = 7; // int -> enum fruits conversion

但是C++ 中的enum 是强类型的。

enum class Traffic_light {red, yellow, green};
enum class Warning {green, yellow, orange, red};

Warning w = 1; // error. no int -> Warning implicit conversion
Traffic_light t = Warning::red; // type error. Warning::red is a different type

【讨论】:

    猜你喜欢
    • 2016-07-08
    • 1970-01-01
    • 2011-11-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多