【问题标题】:Function pointer pointing to functions with different number of arguments指向具有不同数量参数的函数的函数指针
【发布时间】:2021-04-09 18:37:04
【问题描述】:

如何处理将函数分配给一个函数指针,每个函数指针具有不同数量的参数?问题是参数的数量和类型不同。可以的话举个例子。

【问题讨论】:

  • 函数只能在指针类型与函数兼容的情况下通过函数指针调用,即参数的个数/类型相同且返回类型是一样的。
  • 函数指针是否可以与它所指向的函数进行动态调整?
  • 不,需要将函数指针转换为正确的类型。
  • @dbush 那么这个问题没有解决方案吗?你有什么建议吗?
  • 你需要重新考虑你在做什么。函数指针允许您在运行时在具有相同签名的不同函数之间切换。无论如何,您必须为不同数量和类型的参数(和返回值)编写不同的调用。

标签: c function pointers


【解决方案1】:

函数指针可以像其他指针一样被转换。您将拥有一个通用函数指针(类似于存储类型的void *),并使用它来保存/传递函数的地址。在调用该函数之前,您需要将其转换为正确的类型。

这是一个工作示例:

#include <stdio.h>

typedef void (*generic_t)(void);
typedef int  (*type2_t)(int);
typedef int  (*type3_t)(int, char *s);


void test1(void) {
    printf("Test 1\n");
}

int test2(int i) {
    printf("Test 2 %i\n",i);
    return i;
}

int test3(int i, char *s) {
    printf("Test 3 %i, %s\n", i, s);
    return i++;
}

int main(void) {
    generic_t f1, f2, f3;
    f1 = &test1;
    f2 = (generic_t)&test2;
    f3 = (generic_t)&test3;

    f1();
    int i = ((type2_t)f2)(10);
    i = ((type3_t)f3)(20,"This is test");
}

此外,您需要实现一种机制来识别指针所指向的函数类型。一种方法是使用 struct 来保存指针和类型的 enum

【讨论】:

  • &amp; 上的&amp;test1 和朋友是多余的。
  • 我知道这是多余的,但使代码更具可读性。我想添加f1 = (generic_t)&amp;test1,但因为它已经很明显了所以省略了。
  • 我想知道 C 标准是否真的做出了这种定义的行为。对于保证往返转换的函数指针,似乎没有任何与void * 等效的方法。
  • @chqrlie C11 6.3.2.3p8 允许将函数指针转换为另一个函数指针并返回。强制转换是必需的,但它是允许的。
  • @jordanvrtanoski:您可能想要添加对 C 标准的引用:C11 6.3.2.3 指针 p8:指向一种类型的函数的指针可能是转换为指向另一种类型的函数的指针并再次返回;结果应与原始指针比较。如果转换后的指针用于调用类型与引用类型不兼容的函数,则行为未定义。
【解决方案2】:

另一种可能性是创建不同函数指针类型的联合:

union funptr {
    void (*v)();
    void (*vi)(int);
    void (*vs)(char *);
    int  (*i)();
    int  (*ii)(int);
    int  (*iii)(int, int);
    int  (*is)(char *);
};

【讨论】:

    【解决方案3】:

    您可以使用 void 指针来传递对 inout 参数的引用。您可以将多个参数和返回值包装在结构中。返回值可能返回状态。

    有时它用于低级设备驱动程序。

    typedef int func(void *, void *);
    
    func *fptr;
    
    struct s1 
    {
        int i;
        char *s;
    };
    
    int test1(void *in, void *out) 
    {
        printf("Test 1\n");
        return 0;
    }
    
    int test2(void *in, void *out) 
    {
        int *i = in;
        printf("Test 2 %i\n", *i);
        return *i;
    }
    
    int test3(void *in, void *out) 
    {
        struct s1 *s = in;
        printf("Test 3 %i, %s\n", s -> i, s -> s);
        return ++s -> i;
    }
    
    int main(void) 
    {
        fptr = test1;
        fptr(NULL, NULL);
        fptr = test2;
        fptr((int[]){10}, NULL);
        fptr = test3;
        printf("Returned value: %d\n", fptr(&(struct s1){20,"This is test"}, NULL));
    }
    

    【讨论】:

    • 是的 - 这将是我的首选机制。
    【解决方案4】:

    您必须为需要处理的每个不同签名声明一个新的函数指针类型。

    【讨论】:

    • 但是在这种情况下函数指针的目的是什么?
    • @Zmax:函数指针的目的是允许您将调用的函数更改为具有相同参数和返回类型的多个可能函数之一。无论如何,您必须为每个可能的参数列表编写不同的调用。
    • 我理解使用,但在这种具体情况下,它没有任何目的,因为我的函数返回类型和参数的数量/类型不同。
    • @Zmax 但这并不是一件坏事,你为什么认为它是?
    • 我不认为是这样,但在我的情况下,我可以将两个具有相同签名的函数组合在一起,这是很少见的情况,几乎我没有。在那种情况下,我可以直接调用所有这些,而无需引入不必要的函数指针。我想要的是在运行时切换到合适的。
    猜你喜欢
    • 2017-03-26
    • 1970-01-01
    • 2013-05-22
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多