![](/img/trans.png)
[英]Function pointer pointing to functions with different number of arguments
[英]Function pointer to different functions with different arguments in C
我有兩個具有可變數量和參數類型的函數
double my_func_one(double x, double a, double b, double c) { return x + a + b + c }
double my_func_two(double x, double p[], double c) { return x + p[0] + p[1] + c }
我想使用一個指向函數的指針,該函數指向我上面定義的基於某個條件為真的函數,例如
if (condition_1)
pfunc = my_func_one;
else if (condition_2)
pfunc = my_func_two;
// The function that will use the function I passed to it
swap_function(a, b, pfunc);
我的問題是,對於這種情況,我可以定義一個函數指針嗎? 如果是,如何?
我的理解是,函數指針的原型對於它可以指向的所有函數應該是相同的。
typedef double (*pfunction)(int, int);
就我而言,它們不一樣。 有沒有其他方法可以做到這一點?
我正在用 C 進行開發,我正在使用 gcc 4.4.3 編譯器/鏈接器
最干凈的方法是使用聯合:
typedef union {
double (*func_one)(double x, double a, double b, double c);
double (*func_two)(double x, double p[], double c);
} func_one_two;
然后你可以初始化聯合的一個實例,並將信息包含到swap_function
函數來說明哪個字段是有效的:
func_one_two func;
if (condition_1)
func.func_one = my_func_one;
else if (condition_2)
func.func_two = my_func_two;
// The function that will use the function I passed to it
swap_function(a, b, func, condition_1);
這假設swap_function
可以根據condition_1
為false
知道它應該假設condition_2
。 注意聯合是按值傳遞的; 畢竟它只是一個大小的函數指針,所以這並不比傳遞一個指針更昂貴。
我的問題是,對於這種情況,我可以定義一個函數指針嗎?
不。(除了骯臟的類型轉換。)
有沒有其他方法可以做到這一點?
最好的辦法是為現有函數之一創建一個包裝函數。 例如:
double my_func_one_wrapper(double x, double p[], double c) {
return my_func_one(x, p[0], p[1], c);
}
這樣,您就有兩個具有相同簽名的函數,因此具有相同的函數指針類型。
一個老話題,但我面臨同樣的問題,最后提出了這個想法。
如果你想為每個函數使用相同的原型,你可以將參數包裝在這樣的結構中:
typedef struct {
double a,
b,
c;
}chunk1_t;
typedef struct {
double p[];
double c;
}chunk2_t;
然后你的函數指針變成:
double (*pfunc) (double x, void *args);
這導致了這樣的事情:
pfunc cb;
double swap_function(double x, pfunc cb, void *args);
double my_func_one(double x, void *args) {
chunk1_t *chunk = (chunk1_t*) args;
return x + chunk->a + chunk->b + chunk->c;
}
double my_func_two(double x, void *args) {
chunk2_t *chunk = (chunk2_t*) args;
return x + chunk->p[0] + chunk->p[1] + chunk->c ;
}
int main(){
// declare a, b,...
double a = 1.0f;
//...
// cast for safety
chunk1_t myChunk1 = {(double)a, (double)b, (double)c};
// don't if you like risk
chunk2_t myChunk2 = {p, c};
swap_function(x, cb, &myChunk1);
swap_function(x, cb, &myChunk2);
}
使用存儲在結構中的函數指針:
#define FUNC_ONE_METHOD 1
#define FUNC_TWO_METHOD 2
typedef struct chunk{
double a, b, c;
double p[];
int method;
double (*pfunc) (double x, struct chunk *self);
}chunk_t;
double swap_function(double x, chunk_t *ch){
switch (ch->method)
{
case FUNC_TWO_METHOD:
ch->pfunc = my_func_two;
break;
case FUNC_ONE_METHOD:
ch->pfunc = my_func_one;
break;
default:
return -1; // or throw error
return ch->pfunc(x, ch);
}
chunk c = {.a= 1, .b=3, .c=1, .method=1};
swap_function(x, &c);
你的理解是對的。
函數指針的簽名必須與相應的函數匹配。
考慮learncpp.com :
就像可以聲明指向變量的非常量指針一樣,也可以>聲明指向函數的非常量指針。 這樣做的語法是您將看到的最丑陋的事情之一:
// pFoo is a pointer to a function that takes no arguments and returns an integer
int (*pFoo) ();
出於優先考慮,*pFoo 周圍的括號是必需的,因為 int
*pFoo()
將被解釋為名為pFoo
的函數,該函數不接受參數並返回指向整數的指針。在上面的代碼片段中,
pFoo
是一個指向沒有參數並返回整數的函數的指針。pFoo
可以“指向”任何與此簽名匹配的函數。...
請注意,函數指針的簽名(參數和返回值)必須與函數的簽名匹配。
你想要的是可能的,但有點臟。 函數指針可以相互轉換而不會丟失信息。 重要的是,您總是必須通過這樣的指針調用函數,並且只能使用與其定義相對應的簽名。 因此,如果您在調用函數之前回滾並使用正確的參數調用,一切都應該沒問題。
對不同原型的不同函數使用相同函數指針的類型轉換方法示例。 <>
#include <stdio.h>
typedef void (*myFuncPtrType) (void);
typedef int (*myFunc2PtrType)(int, int);
typedef int * (*myFunc3PtrType)(int *);
static void myFunc_1 (void);
static int myFunc_2 (int, int);
static int* myFunc_3 (int *);
const myFuncPtrType myFuncPtrA[] = {
(myFuncPtrType)myFunc_1,
(myFuncPtrType)myFunc_2,
(myFuncPtrType)myFunc_3
};
static void myFunc_1 (void)
{
printf("I am in myFunc_1 \n");
}
static int myFunc_2 (int a, int b)
{
printf("I am in myFunc_2\n");
return (a+b);
}
static int* myFunc_3 (int *ptr)
{
printf("I am in myFunc_3\n");
*ptr = ((*ptr) * 2);
return (ptr+1);
}
int main(void) {
// your code goes here
int A[2],C;
int* PTR = A;
(*(myFuncPtrA[0]))();
A[0]=5;
A[1]=6;
C = ((myFunc2PtrType)(*(myFuncPtrA[1])))(A[0],A[1]);
printf("Value of C: %d \n", C);
printf("Value of PTR before myFunc_3: %p \n", PTR);
printf("Value of *PTR before myFunc_3: %d \n", *PTR);
PTR = ((myFunc3PtrType)(*(myFuncPtrA[2])))(&A);
//Lets look how PTR has changed after the myFunc_3 call
printf("Value of PTR after myFunc_3: %p \n", PTR);
printf("Value of *PTR after myFunc_3: %d \n", *PTR);
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.