对c中具有不同参数的函数进行类型转换

时间:2018-04-10 04:53:14

标签: c casting function-pointers typedef

所以我有两个函数可以做同样的事情但是在不同的类型变量上。

第一个函数在给定int arr[]参数时填充整数数组。 当给定结构作为参数时,第二个函数也用整数填充链表。 链表参数的结构看起来像这样

typedef struct {node_t *head;int size;} 
list_t;       

现在我已经为这两个函数实现了一个函数指针表:

typedef struct{
    char *name;  //name of the function
    void (*fill)(int arr[]); //fill up the array 
} alg_t;

alg_t algs[] = {
    {"func1",fill_up_arr},
    {"func2",fill_up_linkedList}
};

请注意,在包含指针的struct中,fill函数指针 将int arr[]作为参数。

我只想在该结构中使用一个函数的指针,有没有办法可以使用 类型转换,以便其他函数,如fill_up_linkedList要求参数类型为list_t而不是int arr[]

//This is what I want my main to look like.
//I want func.fill to be called only once thus
//dynamically perform the operations for all functions inside the table of 
//functions array
int arr = malloc(sizeof(int)algs.size);
for(int i = 0; i<algs.size;i++){
     alg_t func = algs[i];  
     func.fill(arr);
}                  

似乎这个代码的问题是当循环尝试执行fill_up_LinkedList函数时,因为它需要一个不同的参数。 在这种情况下如何使用类型转换?

由于

4 个答案:

答案 0 :(得分:1)

好消息

C11 §6.3.2.3 Pointers ¶8(在一般主题§6.3 Conversions下)说:

  

指向一种类型的函数的指针可以转换为指向另一种函数的指针   打字再回来;结果应该等于原始指针。如果转换了   指针用于调用类型与引用类型不兼容的函数,   行为未定义。

这意味着您可以将任何和所有函数指针存储在公共函数指针类型中,例如typedef void (*GenericFunctionPointer)(void)。但是,重要的是,在通过指针调用函数之前,从通用函数指针类型转换回正确的函数指针类型(并且您提供了正确的参数列表,并且您正确地处理了返回类型,虽然忽略了返回值,但如果有的话,总是一个选项。)

坏消息

对于两个不同的函数指针类型,每个函数都有一个函数实例,支持它的基础结构可能比节省的更精细,如果有的话。另一方面,如果你有两个或更多不同的函数指针类型,并且大多数(如果不是所有)类型都有许多代表函数('many'表示'多于一个',如计算机工程师的计数:“零,一个,很多“),然后基础设施可以得到回报。其中一个问题是编组函数参数 - 如何使参数可访问,以便可以通过具有正确参数的指针调用该函数。

所以,这样做是复杂而冗长的。

规定的要求

comment中,OP Moi说:

  

我只想在结构中放一个函数。我的目标是找到一种方法,允许fillArray允许传递不同的参数。

我对使用不计数数组作为参数列表有很大的保留,如问题所示 - void (*fill)(int arr[])。在我看来,它应该是void (*fill)(size_t n, int arr[n]),使用可变长度数组表示法。如果您愿意,可以省略下标中的n - void (*fill)(size_t n, int arr[]) - 甚至可以使用void (*fill)(int arr[], size_t n),这是参数的更经典的顺序。

抛开这个问题,如果你想让一个函数接受不同的参数,一种方法就是用void *作为类型,但你必须知道这些问题 - 其中一个是类型安全。您还需要借鉴标准C函数qsort()bsearch()中的想法。参数列表将包含指向数组开头的指针void *,数组中每个元素的大小以及数组中元素的数量。您可能还需要比较器功能的类似物。

在单个被调用函数的内部,你可能最终会得到两个代码路径,所以尽管你通过指针调用一个函数,但你最终还是相当于实现了两个函数。您可以使用类似于qsort()的接口,这样两个函数具有相同的接口和不同的主体,并且您在alg_t数组中使用两个指针。

摘要

  • 您可能无法干净地达到规定的要求。
  • 您可能需要两个逻辑上独立的函数来处理两个独立的接口,即使您在单个函数中刷新所有代码。

答案 1 :(得分:0)

使用联盟:

typedef struct {
    char *name;  //name of the function
    union {
        void(*fillArray)(int arr[]); //fill up the array 
        void(*fillList)(YourListType list); //fill up the list
    };
} alg_t;

alg_t a;
a.fillArray(...);
a.fillList(...);

或者:

typedef struct {
    char *name;  //name of the function
    union {
        void(*fillArray)(int arr[]); //fill up the array 
        void(*fillList)(YourListType list); //fill up the list
    } functions;
} alg_t;

alg_t a;
a.functions.fillArray(...);
a.functions.fillList(...);

答案 2 :(得分:0)

由于您只有2种类型,因此您只需使用枚举和宏

即可
<div class="crumb">
    <div class="arrowWrapper">
        <span class="arrow"></span>
    </div>
</div>

用你的函数名替换foo和bar

答案 3 :(得分:0)

如果您只遇到函数参数的问题而没有返回值,则有一个与不完整的类型定义相关的技巧。诀窍在于将指针类型声明中的参数列表留空,如:

 typedef void (*callback_ptr)();

不同于:

 typedef void (*callback_ptr)(void);

在第一种情况下,编译器不会检查传递给函数的参数,因为指针是指向未完全定义的函数类型的指针,而第二种显式表示该函数不需要参数,并且会给你一个如果您尝试与他们一起调用,则会出错。