C switch 语句和枚举显式转换

C switch statement and enum explicit cast

看到很多类似的问题,但 none 在这里回答我的问题: 假设我有一个枚举 Property:

enum
{
    PROP_A = 1,
    PROP_B,
    N_PROPERTIES
} Property;

当我尝试在这样的 switch 语句中使用它时:

// file test.c
enum
{
    PROP_A = 1,
    PROP_B,
    N_PROPERTIES
} Property;

int main(void)
{
    int a = 0;
    switch ((Property) a)
    {
        case PROP_A:
            break;
        case PROP_B:
            break;
        default:
            break;
    };
    return 0;
}

编译器抛出此错误:

test.c: In function ‘main’:
test.c:11:20: error: expected ‘)’ before ‘a’
   11 |  switch ((Property) a)
      |         ~          ^~
      |                    )

这段代码有什么问题?作为参考,在 GObject 文档中他们有这个片段:


typedef enum
{
  PROP_FILENAME = 1,
  PROP_ZOOM_LEVEL,
  N_PROPERTIES
} ViewerFileProperty;

static GParamSpec *obj_properties[N_PROPERTIES] = { NULL, };

static void
viewer_file_set_property (GObject      *object,
                          guint         property_id,
                          const GValue *value,
                          GParamSpec   *pspec)
{
  ViewerFile *self = VIEWER_FILE (object);

  switch ((ViewerFileProperty) property_id)
    {
    case PROP_FILENAME:
      g_free (self->filename);
      self->filename = g_value_dup_string (value);
      g_print ("filename: %s\n", self->filename);
      break;

    case PROP_ZOOM_LEVEL:
      self->zoom_level = g_value_get_uint (value);
      g_print ("zoom level: %u\n", self->zoom_level);
      break;

    default:
      /* We don't have any other property... */
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
      break;
    }
}

本质上是一样的。因此它必须是可能的。我的版本有什么问题?

您需要在 enum 之前添加 typedef 以将 Property 标识为一种类型。在您提供用于比较的另一个示例中,使用了 typedef

在此声明中

    enum
    {
        PROP_A = 1,
        PROP_B,
        N_PROPERTIES
    } Property;

您声明了一个未命名枚举类型的对象Property

所以在switch语句中

switch ((Property) a)

您对两个对象 Propertya 使用语法错误的表达式。

你的意思好像是

    typedef enum
    {
        PROP_A = 1,
        PROP_B,
        N_PROPERTIES
    } Property;

注意可以直接写

switch ( a )

在 C 中,枚举器的类型为 int。即这些枚举数PROP_A、PROP_B、N_PROPERTIES的类型都是int。因此,您尝试应用的转换(如果正确声明了枚举)是多余的。

Suppose I have an enum Property:

enum
{
    PROP_A = 1,
    PROP_B,
    N_PROPERTIES
} Property;

您的代码没有将 Property 定义为枚举 类型 。它将其声明为 变量 ,其类型是未标记的枚举类型。类型转换运算符必须从类型而非变量构造,因此 (Property) a 无效。

那个演员表也是不需要的。解决问题的一种方法是简单地放弃它:

    switch (a) {
        case PROP_A:
            break;
        case PROP_B:
            break;
        default:
            break;
    }

或者,如果您打算将 Property 定义为类型别名,那么这就是 typedef:

的功能
typedef enum {
    PROP_A = 1,
    PROP_B,
    N_PROPERTIES
} Property;

然而,就我个人而言,我不是 typedef 的粉丝。它有一些很好的用途,但它的应用往往远远超出这些用途。如果我想声明一个我可以在其声明之外引用的枚举类型,那么我将包含一个标记:

enum property {
    PROP_A = 1,
    PROP_B,
    N_PROPERTIES
};

int main(void) {
    int a = 0;
    switch ((enum property) a) {
        case PROP_A:
            break;
        case PROP_B:
            break;
        default:
            break;
    }
    return 0;
}

(包含演员表是为了演示目的——仍然没有必要。)