Как определить массив функций в C
У меня есть структура, содержащая объявление вроде этого:
void (*functions[256])(void) //Array of 256 functions without arguments and return value
И в другой функции я хочу ее определить, но есть 256 функций!
Я мог бы сделать что-то вроде этого:
struct.functions[0] = function0;
struct.functions[1] = function1;
struct.functions[2] = function2;
И так далее, но это слишком утомительно, мой вопрос - есть ли способ сделать что-то вроде этого?
struct.functions = { function0, function1, function2, function3, ..., };
EDIT: исправлена ошибка синтаксиса, как сказал Крис Лутц.
Ответы
Ответ 1
У меня есть структура, содержащая объявление вроде этого:
Нет, нет. Это синтаксическая ошибка. Вы ищете:
void (*functions[256])();
Каков массив указателей на функции. Обратите внимание, однако, что void func()
не является "функцией, которая не принимает аргументов и ничего не возвращает". Это функция, которая принимает неопределенные числа или типы аргументов и ничего не возвращает. Если вам нужны "никакие аргументы", вам это нужно:
void (*functions[256])(void);
В С++ void func()
означает "не принимает аргументов", что вызывает некоторую путаницу (особенно, поскольку функциональность C для void func()
имеет сомнительное значение.)
В любом случае, вы должны typedef
указатель на функцию. Это сделает код бесконечно легче понять, и у вас будет только один шанс (в typedef
), чтобы получить синтаксис неправильно:
typedef void (*func_type)(void);
// ...
func_type functions[256];
В любом случае вы не можете назначить массив, но вы можете инициализировать массив и скопировать данные:
static func_type functions[256] = { /* initializer */ };
memcpy(struct.functions, functions, sizeof(functions));
Ответ 2
Вы можете сделать это динамически... Вот небольшой пример массива динамических функций, выделенного с помощью malloc...
#include <stdio.h>
#include <stdlib.h>
typedef void (*FOO_FUNC)(int x);
void a(int x)
{
printf("Function a: %d\n", x);
}
void b(int x)
{
printf("Function b: %d\n", x);
}
int main(int argc, char **argv)
{
FOO_FUNC *pFoo = (FOO_FUNC *)malloc(sizeof(FOO_FUNC *) * 2);
pFoo[0] = (FOO_FUNC)&a;
pFoo[1] = (FOO_FUNC)&b;
pFoo[0](10);
pFoo[1](20);
return 0;
}
Ответ 3
С вершины моей головы и непроверенной.
// create array of pointers to functions
void (*functions[256])(void) = {&function0, &function1, &function2, ..., };
// copy pointers to struct
int i;
for (i = 0; i < 256; i++) struct.functions[i] = functions[i];
EDIT: исправлена синтаксическая ошибка, как сказал Крис Лутц.
Ответ 4
У меня была та же проблема, это моя небольшая программа для тестирования решения. Это выглядит довольно просто, поэтому я решил поделиться им с будущими посетителями.
#include <stdio.h>
int add(int a, int b) {
return a+b;
}
int minus(int a, int b) {
return a-b;
}
int multiply(int a, int b) {
return a*b;
}
typedef int (*f)(int, int); //declare typdef
f func[3] = {&add, &minus, &multiply}; //make array func of type f,
//the pointer to a function
int main() {
int i;
for (i = 0; i < 3; ++i) printf("%d\n", func[i](5, 4));
return 0;
}
Ответ 5
Вы могли бы это сделать, объявив свой экземпляр структуры:
function_structur fs = { struct_field1,
struct_field2,
{function0, function1, ..., function255},
struct_field3,
... };
Вы не можете использовать этот ярлык для инициализации массивов после объявления массива: если вам нужно это сделать, вам придется делать это динамически (используя цикл, memcpy
или что-то еще).
Ответ 6
Если вы хотите выполнить пост-инициализацию массива с помощью формы типа {func1, func2, ...}
, это может быть выполнено следующим образом (с использованием GCC):
UPD (спасибо Chris Lutz за замечания)
Определите макрос следующим образом:
#define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))
И передайте исходный вектор, используя Составные литералы, как показано ниже:
#include <string.h>
...
void (*functions[256])();
...
FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));