c - 将枚举类型转换为 void* 是错误的/危险的吗?

标签 c type-conversion

整个代码是用 ANSI C 编写的,应该保持原样。 我有一个这样定义的回调:

typedef enum {
    Event_One,
    Event_Two,
    Event_State
} EventEnum;

typedef void (*callback)(EventEnum event, void* data);

回调接收者根据 event 值解释 data。这是组件之间的契约。有时它是一个指向结构的指针,有时它可能是一个字符串,其他情况可能是其他数据。我正在定义一个额外的 event 并设置一个新的“契约(Contract)”,data 是一个枚举。像这样:

typedef enum {
    State_Initial = 0,
    State_Running,
    State_Final
} StateEnum;

然后在代码的某处我有一个回调函数,它正在执行此操作

void ProcessEvent (EventEnum event, void* data)
{
    if (event == Event_State)
    {
         StateEnum state = (StateEnum)data; /* <<<<<<<<<<< */
         switch (state) {
         case State_Initial:
             <...>
             break;
         case State_Running:
             <...>
             break;
         case State_Final:
             <...>
             break;
         }
    }
}

上面的回调是这样调用的:

{
    callback infoCallback = ProcessEvent; /* This is only for example,
                                             done during initialization */
    <...>
    StateEnum someState = State_Running;
    <...>
    infoCallback(Event_State, (void*)someState); /* <<<<<<<<<<<<<<<<<<< */
}

void* 类型转换为 StateEnum 或反过来有什么根本性错误吗?这种方式可能存在哪些陷阱?关于可测试性和可维护性的任何想法?

编辑:代码现在编译、链接和运行正常。我想知道为什么不应该这样做,以及是否有任何必须更改代码的真正原因。

最佳答案

只有指向对象的指针(即不是函数)可以转换为 void * 并返回。您不能将非指针转换为 void * 并返回。因此,将您的调用更改为:

infoCallback(Event_State, &someState);

你的功能是:

StateEnum *state = data;
switch (*state)
...

来自标准(6.3.2.3):

An integer may be converted to any pointer type. Except as previously specified, the result is implementation-defined, might not be correctly aligned, might not point to an entity of the referenced type, and might be a trap representation.

Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.

因此,您所做的是实现定义的。如果您的实现定义将 int 转换为指针并返回,则代码将起作用。 一般,它不可移植。有关详细信息,请参阅 this thread在 comp.lang.c 上。

C99 额外定义了intptr_tuintptr_t 类型,它们是整数类型,并且保证将void * 转换为它们并返回.

关于c - 将枚举类型转换为 void* 是错误的/危险的吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2331187/

相关文章:

C++主要函数及程序

c - c语言中如何初始化数组?

swift - 为什么 Float 到 Double 的转换在运行时失败?

powershell - 将字符串转换为时间跨度

type-conversion - Perl6 类属性中的类型强制

c - c 中的 malloc() 和 free() 数组

C 写入意外字符

c - 让 printf 语句在 openCL 内核代码中工作

c++ - 私有(private)转换函数导致 "ambiguous default type conversion"错误 (c++)

Java int 和 char 之间的隐式转换