Как определить функции внутри массива в C? [Дубликат]

Это также полезно для диапазонов разделения; диапазон (a, b) можно разбить на диапазон (a, x) и (x, b) , тогда как с включенным диапазоном вы будет писать либо x-1 , либо x + 1 . Хотя вам редко приходится разделять диапазоны, вы часто часто разбиваете списки, что является одной из причин нарезки списка l [a: b] включает в себя a-ый элемент, но не b- е. Тогда диапазон , обладающий тем же свойством, делает его хорошо согласованным.

12
задан Jonathan Leffler 13 September 2013 в 20:39
поделиться

6 ответов

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

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

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));
14
ответ дан Chris Lutz 15 August 2018 в 19:41
поделиться
  • 1
    Просто помните, что memcpy () является опасным и не переносимым, поскольку структура может содержать любое количество заполняющих байтов. Если вы используете memcpy (), как показано здесь, вы должны убедиться, что компилятор не имеет дополнения. Обычно через assert(sizeof(the_struct.functions) == sizeof(functions)) или аналогичный. – Lundin 15 March 2011 в 11:33
  • 2
    Это неверно. sizeof(some_struct) возвращает размер структуры + любое необходимое дополнение. См. этот вопрос , например. Использование memcpy выше верно. – Mat 15 March 2011 в 11:43
  • 3
    .. и в этом случае memcpy() в любом случае не используется в структурах - он используется для копирования из одного массива в другой с одинаковым размером, что отлично. Тот факт, что целевой массив является элементом структуры, не имеет значения. – caf 15 March 2011 в 13:27
  • 4
    Вероятно, я должен был заметить, что struct является ключевым словом, поэтому использование его как имени переменной неверно даже для кода примера, который никогда не будет близок к компилятору. – Chris Lutz 16 March 2011 в 01:06
  • 5
    разница между func() и func(void) является лишь вопросом C++, а не C, не так ли? – dhein 21 January 2016 в 08:48

Если вы хотите post -инициализировать массив, используя форму типа {func1, func2, ...}, это может быть выполнено следующим образом (с использованием GCC):

UPD (благодаря Chris Lutz для замечаний)

Определите макрос следующим образом:

#define FUNCTION_VECTOR_COPY(destVec, sourceVec) memcpy(destVec, sourceVec, sizeof(sourceVec))

И передайте исходный вектор, используя Compound Literals , как следует:

#include <string.h>
...
void (*functions[256])();
...
FUNCTION_VECTOR_COPY (functions, ((void(*[])()) {func1, func2, func3}));
0
ответ дан Community 15 August 2018 в 19:41
поделиться
  • 1
    sizeof(funcsFrom) здесь недействителен. Массивы в параметрах функции распадаются на указатели, поэтому ваша функция действительно void setFuncs(void(**funcsTo)(), void(**funcsFrom)()) без информации о sizeof. Вы должны a) использовать макрос, который позволит вам это сделать, или b) передать размер массива в качестве третьего параметра. И если вы делаете b, вы можете даже c) написать макрос оболочки, который автоматически подключается к третьему аргументу на основе sizeof второго. Кроме того, d) используйте sizeof(funcsFrom) / sizeof(funcsFrom[0]) в случае изменения типов, и e) ваша функция в противном случае идентична memcpy. – Chris Lutz 16 March 2011 в 01:11
  • 2
    @ Крис благодарит за важные замечания, я тестировал только 2 значения, поэтому я пропустил проблему sizeof. (Великий!; (d) - нормально, но сначала вы должны проверить, имеет ли источник-источник размер больше 0; (e) - yep, но вы не должны забывать включать string.h. См. Обновленный ответ. – Martin Babacaev 16 March 2011 в 11:20

С вершины моей головы и непроверенной.

// 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: Исправлена ​​синтаксическая ошибка, как сказал Крис Лутц.

1
ответ дан orlp 15 August 2018 в 19:41
поделиться

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

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

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

0
ответ дан peoro 15 August 2018 в 19:41
поделиться

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

#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
ответ дан Swedgin 15 August 2018 в 19:41
поделиться

Вы можете сделать это динамически ... Вот небольшой пример массива динамических функций, выделенного с помощью 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;
}
2
ответ дан TurtleToes 15 August 2018 в 19:41
поделиться
  • 1
    Мой плохой ... неправильный контекст для этого обсуждения ... Вместо этого вы можете использовать typedef для определения типа FOO_FUNC, а затем создать массив FOO_FUNC и использовать имена в качестве инициализаторов ... – TurtleToes 15 March 2011 в 13:43
Другие вопросы по тегам:

Похожие вопросы: