Как определить массив функций в C - PullRequest
14 голосов
/ 15 марта 2011

У меня есть структура, которая содержит объявление вроде этого:

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, ..., };

РЕДАКТИРОВАТЬ : синтаксическая ошибка исправлена, как сказал Крис Латс.

Ответы [ 6 ]

18 голосов
/ 15 марта 2011

У меня есть структура, которая содержит объявление вроде этого:

Нет, нет. Это синтаксическая ошибка. Вы ищете:

void (*functions[256])();

Какой массив указателей на функции. Однако обратите внимание, что void func() не является «функцией, которая не принимает аргументов и ничего не возвращает». Это функция, которая принимает неопределенные числа или типы аргументов и ничего не возвращает. Если вы хотите «без аргументов», вам нужно это:

void (*functions[256])(void);

В C ++ 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));
4 голосов
/ 02 марта 2016

У меня была такая же проблема, это моя маленькая программа для тестирования решения.Это выглядит довольно просто, поэтому я решил поделиться им с будущими посетителями.

#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;
}
2 голосов
/ 15 марта 2011

Вы можете сделать это динамически ... Вот небольшой пример массива динамических функций, выделенных с помощью 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] = &a;
    pFoo[1] = &b;

    pFoo[0](10);
    pFoo[1](20);

    return 0;
}
1 голос
/ 15 марта 2011

С макушки головы и непроверено.

// 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];

РЕДАКТИРОВАТЬ : исправлена ​​синтаксическая ошибка, как сказал Крис Латс.

0 голосов
/ 15 марта 2011

Если вы хотите опубликовать -инициализировать массив, используя форму, подобную {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}));
0 голосов
/ 15 марта 2011

Это можно сделать при объявлении экземпляра структуры:

function_structur fs = { struct_field1,
                         struct_field2,
                         {function0, function1, ..., function255},
                         struct_field3,
                         ... };

Этот ярлык нельзя использовать для инициализации массивов после объявления массива: если вам нужно это сделать, вам придется сделатьэто динамически (используя цикл, memcpy или что-то еще).

...