整个代码都是用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_t
和uintptr_t
类型,这两种类型是整数类型,并且保证将avoid *
转换为它们并返回。