显式声明函数指针而不是数据指针

时间:2016-01-10 02:01:28

标签: c visual-c++ function-pointers

我正在使用Microsoft Visual Studio将程序从C ++转换为C.这是一个Windows应用程序,但我认为这与此问题无关。

我正在使用/W4开关打开更多警告消息。我想我的程序编译没有警告。该程序编译并运行正常。这只是警告信息。

在程序是C ++之前,它编译时没有任何警告,但是现在我已经尽可能地将它转换为C,但是有一个警告,我不知道如何处理。

这是相关代码。我的想法是我正在为GUI创建一个菜单系统。每个菜单都包含一组菜单项,每个菜单项都包含一个函数指针,表示用户选择该菜单项时将执行的操作。

typedef struct MENUITEM
{
    wchar_t* Name;
    void*    Action;
} MENUITEM;

typedef struct MENU
{
    wchar_t*   Name;
    uint8_t    SelectedItem;
    uint8_t    ItemCount;
    MENUITEM** Items;
} MENU;

在程序的其他地方,这是用户选择菜单项时处理事件的代码:

void(*FP) (void) = NULL;
FP = (void(*)())MyMenu.Items[MyMenu.SelectedItem]->Action;
FP();

以下是生成的编译器警告:

  

C4152非标准扩展,表达式中的函数/数据指针转换

  

C4113'void(__ cdecl *)()'参数列表与'void(__ cdecl *)(void)'

不同

警告信息C4152的MSDN documentation声明:

  

函数指针转换为数据指针或从数据指针转换。在Microsoft扩展(/ Ze)下允许此转换,但在ANSI C下不允许。

好的,所以我认为这解释了为什么它没有像C ++那样产生警告,但是当编译为C时,它确实如此。但我不知道如何处理它。说实话,我之前没有意识到函数指针和数据指针之间存在差异。

我无法弄清楚如何更改函数指针的声明,以便编译器明确指出这是函数指针,而不是数据指针。

2 个答案:

答案 0 :(得分:5)

你可能需要这个(typedef):

typedef void(*FP) (void);

typedef struct MENUITEM
{
    wchar_t* Name;
    FP   Action;
} MENUITEM;

int main() {

    MENUITEM it;
    // ... more code

    FP fp = it.Action;
    fp();

    return 0;
}

答案 1 :(得分:3)

你忘记了演员阵容中的Action。这就是C4113告诉你的。

您可以通过将void (*Action)(void); 声明为函数指针来完全避免强制转换:

int