Перейти к содержанию
    

[Вроде решено] Массив указателей на функции. Указатель на массив

Запутался. Честно скажу, с указателями я не всегда дружу. :) Помогите написать правильно. Нужно: есть массивы указателей на функцию. И переменные-состояния конечных автоматов, индексы для массивов.

//************************************************************************
//************************ Главный автомат *******************************
//************************************************************************

//========================================================================
STATE (PROC_DEVICE_INIT,             proc_device_init)
STATE (PROC_DEVICE_WAIT_SWITCH_MODE, proc_device_wait_switch_mode)
STATE (PROC_DEVICE_MANUAL,           proc_device_manual_mode)
STATE (PROC_DEVICE_AUTOMAT,          proc_device_automat_mode)
STATE (PROC_DEVICE_EMERG_MODE,       proc_device_emerg_mode)
//========================================================================

enum _proc_device
{
#define STATE(name, func) name,
#include "_proc_device.h"
#undef STATE

  PROC_DEVICE_STATES,
};

//========================================================================
typedef void (*FUNC)(void);
//========================================================================

__flash FUNC proc_device_func [PROC_DEVICE_STATES] =
{
#define STATE(name, func) func,
#include "_proc_device.h"
#undef STATE
};

static u08 _proc_device;
static u08 _proc_device_slave;

void proc_device (void)
{
//   proc_sens_pwr (SAVE_EEPROM_PARAMETERS); // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

  proc_device_func [_proc_device] (); // В данный момент работает так.
}

 

Мне нужна функция, у которой в качестве параметров proc_device_func и _proc_device.

Что-то вроде proc_fsm_func (proc_device_func, get_proc_device_state ())

 

Мои пробы выдают ошибки.

Изменено пользователем demiurg1978

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Нужно: есть массивы указателей на функцию. И переменные-состояния конечных автоматов, индексы для массивов.

Мне нужна функция, у которой в качестве параметров proc_device_func и _proc_device.

Что-то вроде proc_fsm_func (proc_device_func, get_proc_device_state ())

 

Ваш вопрос очень путанно сформулирован.

Как-то так.

typedef void (*t_func)(void);

enum s_state{
    STATE1,
    STATE2
};

void func_state1()
{
    printf("func_state1\n");
}

void func_state2()
{
    printf("func_state2\n");
}

t_func funcs[] =
{
    [STATE1] func_state1 ,
    [STATE2] func_state2 ,
};

void func_run(t_func* funcs, enum s_state state)
{
    (*funcs[state])();
}


int main()
{
    func_run(funcs, STATE1);
    func_run(funcs, STATE2);
...

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне нужна функция, в качестве параметров которой указатель на массивы указателей на функции, и индексы-переменные-состояния КА. В вашем примере вызов функций конкретного массива по конкретному индексу. А мне нужен вызов функций по указанным в параметрах функции массивам и индексам.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне нужна функция, в качестве параметров которой указатель на массивы указателей на функции, и индексы-переменные-состояния КА. В вашем примере вызов функций конкретного массива по конкретному индексу. А мне нужен вызов функций по указанным в параметрах функции массивам и индексам.

поправил

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Мне нужна функция, в качестве параметров которой указатель на массивы указателей на функции

Нверное, как-то так:

int func (int (*func_ptr[])(int), int y)
{

}

Синтксис Си в отношении скобок и звёздочек непротиворечив, но с первого взгляда бывает трудно разобраться, что там к чему. Поэтому надо разбить на части. Сначала определяем тип "указатель на функцию":

typedef int (*pfunc)(int x);

Потом используем этот тип в определении функции

int func (pfunc f[], int y)
{

}

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Определяем тип переменной PROCEDURE - указатель на функцию

 

typedef void (*PROCEDURE)(void);

 

Пишем текст функций.

 

void function1(void) { ... }
void function2(void) { ... }
void function3(void) { ... }

 

Определяем, сколько у нас функций в массиве.

 

#define STATES 3

 

Создаем массив указателей на функции в программной памяти, что у нас, AVR..

 

 __flash const PROCEDURE function[STATES_QTY] = { function1, function2, function3 };

 

Все, в программе вызываем вызываем функцию, соответствующую номеру состояния state:

 

 function[state]();

 

 

 

 

Мне нужна функция, у которой в качестве параметров proc_device_func и _proc_device.

Что-то вроде proc_fsm_func (proc_device_func, get_proc_device_state ())

 

А зачем так сложно - в функцию передавать указатель на функцию? Чтобы вызвать? Ну так вызовите добавлением скобок.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

А зачем так сложно - в функцию передавать указатель на функцию? Чтобы вызвать? Ну так вызовите добавлением скобок.

Покажите, как.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Покажите, как.

Уже сделано! Функция вызывается по индексу в таблице:

 

function[state]();

 

Что не устраивает?

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все приведенные примеры по сути повторяют то, что написано в первом сообщении. Излишняя навороченность кода в том сообщении, по сути enum и массив, обвернутые в макросы. И вызов функции один в один как у вас.

   proc_device_func [_proc_device] ();

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Все приведенные примеры по сути повторяют то, что написано в первом сообщении. Излишняя навороченность кода в том сообщении, по сути enum и массив, обвернутые в макросы. И вызов функции один в один как у вас.

Правильно, макросы вредны, а все остальное - классика, которую использует каждый второй.

Что не устраивает то?

 

Вам то зачем дополнительная прослойка в виде функции, в которую будете передавать указатель на функцию?

Будьте проще, пишите как есть, все же работает.

 

 

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Вроде решил вопрос.

//========================================================================
typedef void (*FUNC)(void);
//========================================================================

void proc_fsm_func (FUNC __flash *ptr_func, u08 s);

void func_1 (void);
void func_2 (void);
void func_3 (void);
void func_4 (void);

extern FUNC __flash list_func [];
void __flash * get_list_func (void);

void func_1 (void)
{

}

void func_2 (void)
{

}

void func_3 (void)
{

}

void func_4 (void)
{

}

__flash FUNC list_func [4] =
{
  func_1,
  func_2,
  func_3,
  func_4,
};

void proc_fsm_func (FUNC __flash *ptr_func, u08 s)
{
  ptr_func [s] ();
}

void __flash * get_list_func (void)
{
  return list_func;
}

     proc_fsm_func (get_list_func (), 2);

 

Задумка такая: что-то вроде ядра обработчика конечных автоматов. Можно было и так оставить, как сделано в первом сообщении. Для каждого автомата своя строка вызова функции по индексу.

А когда задумал ядро обработчика, тут и возникли трудности. Честно говоря, я еще думаю, стоит ли дальше работать над этим ядром и применять его в проектах.

Изменено пользователем demiurg1978

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Для каждого автомата своя строка вызова функции по индексу.

Это реализуется очень просто - одним массивом всех функций, но группы индексов массива для каждого автомата не должны перекрываться.

Например, первые 6 функций - автомат А, следующие 19 функций автомат B, и еще 9 функций автомата C.

тогда если массив называется f, обработка всех автоматов будет выглядеть так:

 

 f[stateA]();
f[stateB]();
f[stateC]();

 

Я так делал один раз в очень специфическом проекте.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Еще на ассемблере я использовал функции очистки ОЗУ. В сишные компиляторах это заложено как стандарт. И это дает нам замечательную штуку. Нулевое состояние конечного автомата используем для инициализации ввода-вывода, периферии, переменных. До использования КА я использовал для этого флаги.

В вашем случае есть начальные состояния КА, которые не равны нулю. А это неудобно. Должна быть обязательная функция инициализации.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Например, первые 6 функций - автомат А, следующие 19 функций автомат B, и еще 9 функций автомата C.

Я так делал один раз в очень специфическом проекте.

Допустим нужно добавить еще несколько состояний в автомат A, что делать? Менять условия всякий раз?;)

Насколько понимаю, ТС разбивает весь код на задачи и у каждой задачи - свой автомат состояний. Т.е. при переключении на соответствующую задачу должен подключаться соответствующий автомат состояния.

В принципе, очень типичная задача. Ничего специфического. Даже тема была https://electronix.ru/forum/index.php?showt...=136908&hl=

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...