C:我如何使用一个函数指针数组来处理变量参数计数?

时间:2021-04-15 00:37:30

The question pretty much says it all.

这个问题几乎说明了一切。

I'm not sure how to do this and haven't come anywhere near anything that works.

我不知道该怎么做,也不知道怎么做。

Here's some example functions:

这里有一些例子功能:

add(int x, int y) {
  return x+y;
}

and,

而且,

mean(int x1, int y1, int x2, int y2) {
  return (x1 + y1 + x2 + y2) / 4;
}

So far I've tried using typedef with both, but I can't figure how to make something point to one of either type:

到目前为止,我已经尝试在这两种类型中使用typedef,但是我不知道如何使某样东西指向其中一种类型:

typedef int (*mathfunc2)(int x, int y);
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2);

????? func_table[2] = {add, mean};

4 个解决方案

#1


26  

You need to pick a function pointer type to use as a "generic function pointer", use that type to define your array, and use explicit casts. Casting one function pointer type to another and then back again is guaranteed to preserve the value.

您需要选择一个函数指针类型作为“通用函数指针”,使用该类型定义数组,并使用显式强制转换。将一个函数指针类型转换为另一个函数指针类型,然后再转换回该函数指针类型,可以确保保留该值。

In other words:

换句话说:

typedef int (*generic_fp)(void);

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean };

Then to call add, you need to cast it back to the right type:

然后调用add,您需要将它转换回正确的类型:

result = ((mathfunc2)func_table[0])(x, y);

You can define some macros if you find it more palatable:

如果你觉得一些宏更容易接受,你可以定义一些宏:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2)
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4)

result = FUNC_2(func_table[0], x, y);

#2


3  

You could use the Facade Pattern like this:

您可以使用如下的Facade模式:

int add(int x, int y);
int mean(int x1, int y1, int x2, int y2);

typedef int (*operation_fp)(int argc, int* argv);

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); }
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); }

operation_fp func_table[2] = { add_wrapper, mean_wrapper };

Although the code is ugly, it does the job. You should add some validation logic in wrappers.

尽管代码很难看,但它确实能做到这一点。您应该在包装器中添加一些验证逻辑。

#3


1  

int (*func[])() = { add, mean };

#4


0  

These two function types are incompatible. Strictly speaking, they could be implemented using completely different argument passing. An implementation might choose, for example, that all functions with up to 3 parameters receive them via registers, and all other functions receive them via the stack.

这两种函数类型是不兼容的。严格地说,它们可以使用完全不同的参数传递来实现。一个实现可以选择,例如,所有具有3个参数的函数都可以通过寄存器接收它们,所有其他函数都可以通过堆栈接收它们。

What you can do though is to define both functions with varargs parameters to make them follow the same parameter passing scheme.

不过,您可以使用varargs参数定义这两个函数,使它们遵循相同的参数传递方案。

How did you intend to call these functions anyway, not knowing how many parameters they expect?

无论如何,您打算如何调用这些函数,不知道它们期望多少参数?

#1


26  

You need to pick a function pointer type to use as a "generic function pointer", use that type to define your array, and use explicit casts. Casting one function pointer type to another and then back again is guaranteed to preserve the value.

您需要选择一个函数指针类型作为“通用函数指针”,使用该类型定义数组,并使用显式强制转换。将一个函数指针类型转换为另一个函数指针类型,然后再转换回该函数指针类型,可以确保保留该值。

In other words:

换句话说:

typedef int (*generic_fp)(void);

generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean };

Then to call add, you need to cast it back to the right type:

然后调用add,您需要将它转换回正确的类型:

result = ((mathfunc2)func_table[0])(x, y);

You can define some macros if you find it more palatable:

如果你觉得一些宏更容易接受,你可以定义一些宏:

#define FUNC_2(f, p1, p2) ((mathfunc2)(f))(p1, p2)
#define FUNC_4(f, p1, p2, p3, p4) ((mathfunc4)(f))(p1, p2, p3, p4)

result = FUNC_2(func_table[0], x, y);

#2


3  

You could use the Facade Pattern like this:

您可以使用如下的Facade模式:

int add(int x, int y);
int mean(int x1, int y1, int x2, int y2);

typedef int (*operation_fp)(int argc, int* argv);

int add_wrapper(int argc, int* argv) { return add(argv[0], argv[1]); }
int mean_wrapper(int argc, int* argv) { return mean(argv[0], argv[1], argv[2], argv[3]); }

operation_fp func_table[2] = { add_wrapper, mean_wrapper };

Although the code is ugly, it does the job. You should add some validation logic in wrappers.

尽管代码很难看,但它确实能做到这一点。您应该在包装器中添加一些验证逻辑。

#3


1  

int (*func[])() = { add, mean };

#4


0  

These two function types are incompatible. Strictly speaking, they could be implemented using completely different argument passing. An implementation might choose, for example, that all functions with up to 3 parameters receive them via registers, and all other functions receive them via the stack.

这两种函数类型是不兼容的。严格地说,它们可以使用完全不同的参数传递来实现。一个实现可以选择,例如,所有具有3个参数的函数都可以通过寄存器接收它们,所有其他函数都可以通过堆栈接收它们。

What you can do though is to define both functions with varargs parameters to make them follow the same parameter passing scheme.

不过,您可以使用varargs参数定义这两个函数,使它们遵循相同的参数传递方案。

How did you intend to call these functions anyway, not knowing how many parameters they expect?

无论如何,您打算如何调用这些函数,不知道它们期望多少参数?