C: Как я могу использовать единый массив указателей функций для функций с переменными параметрами?
Вопрос в значительной степени говорит обо всем.
Я не уверен, как это сделать, и нигде не приближается к чему-либо, что работает.
Вот некоторые примеры функций:
add(int x, int y) {
return x+y;
}
и
mean(int x1, int y1, int x2, int y2) {
return (x1 + y1 + x2 + y2) / 4;
}
До сих пор я пытался использовать typedef для обоих, но я не могу понять, как сделать что-то одно из одного типа:
typedef int (*mathfunc2)(int x, int y);
typedef int (*mathfunc4)(int x1, int y1, int x2, int y2);
????? func_table[2] = {add, mean};
Ответы
Ответ 1
Вам нужно выбрать тип указателя функции для использования в качестве "универсального указателя функции", использовать этот тип для определения вашего массива и использовать явные приведения. При сохранении значения гарантируется сохранение только одного типа указателя на функцию, а затем обратно.
Другими словами:
typedef int (*generic_fp)(void);
generic_fp func_table[2] = { (generic_fp)add, (generic_fp)mean };
Затем, чтобы вызвать add
, вам нужно вернуть его в нужный тип:
result = ((mathfunc2)func_table[0])(x, y);
Вы можете определить некоторые макросы, если найдете их более приемлемыми:
#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
Вы можете использовать Facade Pattern следующим образом:
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 };
Хотя код уродливый, он выполняет эту работу. Вы должны добавить логику проверки в оболочку.
Ответ 3
int (*func[])() = { add, mean };
Ответ 4
Эти два типа функций несовместимы. Строго говоря, они могут быть реализованы с использованием совершенно разных аргументов. Например, реализация может выбрать, что все функции с тремя параметрами получают их через регистры, а все остальные функции получают их через стек.
Однако вы можете определить обе функции с параметрами varargs, чтобы заставить их следовать той же схеме прохождения параметров.
Как вы намеревались называть эти функции в любом случае, не зная, сколько параметров они ожидают?