C函数指针转换为另一个函数指针

时间:2015-06-11 15:36:20

标签: c function pointers function-pointers

我需要函数指针的帮助。

我有两个函数指针类型:

typedef void (*draw_func1_t)(void* data, void* painter, double x, double y);
typedef void (*draw_func2_t)(void* data, MyPainter* painter, double x, double y);

除了第二个参数外,这两种类型几乎相同。现在我需要编写一个将draw_func1_t转换为draw_func2_t的函数:

draw_func2_t convert_func_p(draw_func1_t func) { ... }

我怎么写呢?我可以强迫演员像

return (draw_func2_t)func;

因为两个函数原型是二进制兼容的吗?

4 个答案:

答案 0 :(得分:5)

如果将函数指针强制转换为其他类型,则其调用的行为未定义。见C标准的附录J.2:

  

在以下情况下,行为未定义:指针   用于调用类型与其不兼容的函数   指向型(6.3.2.3)。

兼容性在6.7.5.1第2段中处理:

  

要使两个指针类型兼容,两者应完全相同   限定,两者都是兼容类型的指针。

MyPainter*void*不兼容。因此,您的函数指针强制转换不能用于调用函数。

答案 1 :(得分:1)

自使用以来:

HttpRequest.CreateResponse()

导致未定义的行为,您可能想要更改策略。

说你有:

draw_func1_t convert_func_p(draw_func2_t func)
{
   return (draw_func1_t)func;
}

并且您希望能够通过函数指针间接使用该函数。

一种选择是使用包装函数。

void func2(void* data, MyPainter* painter, double x, double y)
{
   printf("In func2, working with MyPainter\n");
}

注册void func2_wrapper(void* data, void* painter, double x, double y) { // In this function, if you are sure that painter points to // a valid MyPainter object, you can do this: MyPainter* realPainter = (MyPainter*)painter; // Then call the core function. func2(data, realPainter, x, y); } 作为回调。

您还可以通过删除func2_wrapper的显式转换来简化func2_wrapper

MyPainter*

答案 2 :(得分:0)

理论上,如果你将它转换为不同的签名并调用它,那么它是未定义的行为,正如Bathsheba的答案所引用的那样,因为调用不同类型函数的调用约定可能不同。

然而,实际上,它几乎适用于任何真实世界的系统,因为几乎所有的调用约定都相同地处理不同类型的(非函数)指针。由于这是唯一的区别(其他一切,包括参数的数量和返回类型是相同的),调用约定几乎肯定是相同的。您可以检查特定系统的函数调用ABI以确保。

答案 3 :(得分:0)

以下编译时没有警告(VC2008),并显示两种功能类型兼容。出乎意料的是,在void *被要求的情况下接受MyPainter *

typedef struct {
    int x;
    int y;
} MyPainter;

typedef void (*draw_func1_t)(void* data, void* painter, double x, double y);
typedef void (*draw_func2_t)(void* data, MyPainter* painter, double x, double y);

void f1(void* data, void* painter, double x, double y);
void f2(void* data, MyPainter* painter, double x, double y);

void f1(void* data, void* painter, double x, double y)
{
    f2(data,painter,x,y);   // no compiler warning is unexpected
}
void f2(void* data, MyPainter* painter, double x, double y)
{
    f1(data,painter,x,y);   // no compiler warning is expected
}
void pTest(void)
{
    MyPainter p = {0,0};
    draw_func1_t pf1;
    draw_func2_t pf2;

    pf1= f1;
    pf2= f1;

    pf1= f2;
    pf2= f2;

    pf1(0,&p,0.0,0.0);
    pf2(0,&p,0.0,0.0);
}