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)
您对两个对象 Property
和 a
使用语法错误的表达式。
你的意思好像是
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;
}
(包含演员表是为了演示目的——仍然没有必要。)
看到很多类似的问题,但 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)
您对两个对象 Property
和 a
使用语法错误的表达式。
你的意思好像是
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;
}
(包含演员表是为了演示目的——仍然没有必要。)