整个代码是用ANSI C编写的,它应该保持不变.我有一个像这样定义的回调:
typedef enum {
Event_One,
Event_Two,
Event_State
} EventEnum;
typedef void (*callback)(EventEnum event, void* data);
Run Code Online (Sandbox Code Playgroud)
回调接收者data根据event值解释.这是组件之间的契约.有时它是指向结构的指针,有时它可能是一个字符串,其他情况可能是其他数据.我正在定义一个额外的event并设置一个新的"合同",这data是一个枚举.像这样:
typedef enum {
State_Initial = 0,
State_Running,
State_Final
} StateEnum;
Run Code Online (Sandbox Code Playgroud)
然后代码中的某个地方我有一个回调函数,就是这样做的
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
上面的回调被调用如下:
{
callback infoCallback = ProcessEvent; /* This is only for example,
done during initialization */
<...>
StateEnum someState = State_Running;
<...>
infoCallback(Event_State, (void*)someState); /* <<<<<<<<<<<<<<<<<<< */
}
Run Code Online (Sandbox Code Playgroud)
有什么根本性的错误类型映射void*到StateEnum反之亦然?这种方式有什么可能的陷阱?关于可测试性和可维护性的任何想法?
编辑:代码编译,链接和运行正常.我想知道为什么不应该这样做,以及是否有任何真正的原因必须更改代码.
只有指向对象的指针(即非函数)才能转换void *回来.您无法将非指针转换为void *和返回.所以,将您的电话改为:
infoCallback(Event_State, &someState);
Run Code Online (Sandbox Code Playgroud)
你的功能是:
StateEnum *state = data;
switch (*state)
...
Run Code Online (Sandbox Code Playgroud)
从标准(6.3.2.3):
整数可以转换为任何指针类型.除非先前指定,否则结果是实现定义的,可能未正确对齐,可能不指向引用类型的实体,并且可能是陷阱表示.
任何指针类型都可以转换为整数类型.除非先前指定,否则结果是实现定义的.如果结果无法以整数类型表示,则行为未定义.结果不必在任何整数类型的值范围内.
所以,你正在做的是实现定义.如果您的实现将其定义为可以转换int为指针并返回,则代码将起作用. 一般来说,它不便携.有关更多详细信息,请参阅comp.lang.c上的此主题.
C99另外限定类型intptr_t和uintptr_t,它们是整体的类型,以及它是保证一个转换void *到它们并返回.