"generic" 函数指针使用哪种数据类型?

Which data type to be used for a "generic" function pointer?

根据本站各种问题的回答(link, link, link),不允许将函数指针转换为数据指针。

这对我来说很有意义,因为在某些 CPU 架构中,函数指针比数据指针长:通过将函数指针转换为数据指针,数据将会丢失。

桌面程序的历史示例是具有“中等”内存布局的 x86-16(sizeof(void (*)())=4sizeof(void *)=2);您仍然会在某些现代(主要是非桌面)CPUs.

中发现这种行为

如果变量应包含指向“未知”数据的指针,则使用数据类型 void *

我目前正在编写一个程序,其中变量可能包含指向“未知”函数的指针(就像 Linux 中的 dlsym() 或 Linux 中的 GetProcAddress() 返回的值一样Windows):

// ---- file1.c ----

typedef /* What to use here? */ functionPointer;
...
functionPointer myPointer, myPointer2;
myPointer = getFunction(1);
myPointer2 = getFunction(2);
...
double (*fptr)(double, void *) = myPointer2;
...

// ---- file2.c ----

void func1(void);
double func2(double x, void * y);

functionPointer getFunction(int which)
{
    switch(which)
    {
    case 1: return &func1;
    case 2: return &func2;
    ...
    }
}

如果程序应该与平台无关,在这种情况下会使用哪种数据类型?

如果没有适用于所有平台(桌面、微控制器、DSP、GPU 等)的解决方案:

是否有适用于所有桌面的解决方案?

您在平台列表中加入了“GPU”。有些 GPU 甚至不支持真正的函数调用,而只支持内联和展开(即在 OpenCL 中)。与“goto”命令相同。甚至不允许从函数的另一个入口点进入。

如果可以,对函数标识符数组进行排序(提示要调用哪个函数)。然后把不同的chunk分成不同的数组,然后在各自的kernel中调用。如果有 100 个不同的函数,那么你可以在数组排序后在它们自己的内核中调用所有这些函数。这甚至优化了 GPU 着色器的分支性能问题。内核完成后,您可以继续主要算法。

对于通用函数指针,使用任何函数指针类型。

C 2018 6.3.2.3 8 说:

A pointer to a function of one type may be converted to a pointer to a function of another type and back again; the result shall compare equal to the original pointer…

这意味着您可以将任何函数指针转换为不同类型的函数指针。只要你在调用函数的时候把它转回原来的类型,定义了行为,就会正确调用原来的函数。

C 不提供指定的通用函数指针类型,如 void * 对象。您只需为您的程序选择一个,例如 void (*)(),然后使用它。