Как определить массив функций в 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}));