首页 文章

指向任何功能?

提问于
浏览
7

如何声明一个可以安全指向任何函数的函数指针?

我需要类似 void 指针的东西,但是对于函数来说 . 我想过简单地使用它,但根据this question的答案,函数指针无法可靠地转换为数据指针,至少在非POSIX系统上 .

我搜索并找到了一些可能的例子:

int (FAR WINAPI * FARPROC) ()

文档还提到了这一点:

在C中,FARPROC声明指示具有未指定参数列表的回调函数 .

听起来不错,但回报值呢?它明确指定为 int .

typedef void (*GLfunction)();
extern GLfunction glXGetProcAddressARB(const GLubyte *procName);

参数列表也未指定,但返回类型明确指定为 void .

我不知道如何解释这一点 . 在使用之前,函数指针将使用适当的原型强制转换为函数指针类型 . 例如:

typedef void (*function_pointer_t)();
extern function_pointer_t get_function(const char * name);

/* Somewhere else... */

typedef double (*cosine_function_t)(double);
cosine_function_t cosine = (cosine_function_t) get_function("cos");

这段代码安全吗?它是否违反任何C标准或导致任何未定义的行为?

2 回答

  • 12

    首先,'s no way to declare a function pointer that would be able to accept any function pointer type without a cast. The problem, as you already noted yourself, is that any function pointer declaration immediately assumes a specific return type. So, there'在函数指针世界中没有 void * 的全部模拟 .

    其次,只要您通过使用显式强制转换强制转换,任何函数指针都可用于存储任何其他函数指针值 . 当然,为了通过强制转换为不同类型的指针执行正确的调用,您需要将其转换回原始类型 . 即只要在调用时恢复正确的函数指针类型,这不会导致任何未定义的行为 .

    在您的示例中,如果 get_function 返回的指针确实指向 double (double) 类型的函数,则通过 cosine 指针调用该函数是完全安全的 . 指针值中间存储在 void (*)() 指针中的事实不会破坏它 .

    第三,在C语言中, () 参数声明代表未指定的数量和参数类型 . 这是"universal"函数指针类型的一个步骤,可以在没有强制转换的情况下使用(只要您在调用中提供适当的参数并且只要返回类型匹配)

    void foo();
    void bar(int i);
    void baz(long i, double x);
    
    int main() {
      void (*a[3])() = { foo, bar, baz };
      a[0]();
      a[1](42);
      a[2](5L, 3.1415);
    }
    

    但是,同样,返回类型的问题仍然存在 .

  • 2

    你可以使用联盟 . 肯定只有有限数量的函数类型可以通过这个指针调用,你可以将它们全部放在联合中 .

相关问题