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

Explicitly declaring a function pointer and not a data pointer

我正在使用 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 nonstandard extension, function/data pointer conversion in expression

C4113 'void (__cdecl *)()' differs in parameter lists from 'void (__cdecl *)(void)'

警告消息 C4152 的 MSDN documentation 指出:

A function pointer is converted to or from a data pointer. This conversion is allowed under Microsoft extensions (/Ze) but not under ANSI C.

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

我不知道如何更改函数指针的声明,以便编译器明确知道这是函数指针,而不是数据指针。

您可能需要这个(带有 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;
}

您忘记了演员表中的 void。这就是 C4113 告诉你的。

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

void (*Action)(void);