整个代码都是用ansi c编写的,应该保持原样。
我有一个回调定义如下:

typedef enum {
    Event_One,
    Event_Two,
    Event_State
} EventEnum;

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

回调接收者根据data值解释event。这是部件之间的合同。有时它是指向结构的指针,有时它可能是字符串,其他情况可能是其他数据。我正在定义一个额外的event并设置一个新的“契约”,它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):
整数可以转换为任何指针类型。除非前面指定,否则结果是实现定义的,可能未正确对齐,可能未指向引用类型的实体,并且可能是陷阱表示。
任何指针类型都可以转换为整数类型。除非前面指定,否则结果是实现定义的。如果结果不能用整数类型表示,则行为未定义。结果不必在任何整数类型的值范围内。
所以,您要做的是定义实现。如果您的实现定义可以将int转换为指针并返回,那么代码将工作。一般来说,它是不可携带的。有关详细信息,请参见comp.lang.c上的this thread
c99还定义了intptr_tuintptr_t类型,这两种类型是整数类型,并且保证将avoid *转换为它们并返回。

10-05 22:44
查看更多