[uquote="ARV",url="/forum/viewtopic.php?p=3816167#p3816167"]по-моему, и лаконичность, и понятность не пострадала в данном случае[/uquote]Да причём тут лаконичность? Мне на неё положить - один раз написал и забыл. Подумай, какой код даст твой макрос на вот таком простом коде
[uquote="ARV",url="/forum/viewtopic.php?p=3816542#p3816542"]А кто-то этого не знал?[/uquote]Получается, что нет. Иначе зачем спрашивать было?
[uquote="ARV",url="/forum/viewtopic.php?p=3815975#p3815975"]Почему? Или чем хужее?[/uquote]
[uquote="ARV",url="/forum/viewtopic.php?p=3816542#p3816542"]Речь шла о том, как реверсировать константы, для этого функция не обязательна.[/uquote]Я это в первом же ответе написал. Что можно макросом или функцией.
[uquote="ARV",url="/forum/viewtopic.php?p=3815975#p3815975"]Тем более что увеличивает объём кода.[/uquote]Функция как раз таки уменьшает размер кода.
PS: Это, кстати, было не единственное слабое место макроса.
VladislavS писал(а):Это, кстати, было не единственное слабое место макроса
так я и спрашиваю о слабостях.
в контексте вопроса о константных вычислениях функция проигрывает полностью по размеру кода, т.к. макрос вообще не порождает код, а функция - порождает.
а в чем еще слабость макроса в упомянутом контектсе?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
[uquote="ARV",url="/forum/viewtopic.php?p=3816695#p3816695"]в контексте вопроса о константных вычислениях функция проигрывает полностью по размеру кода, т.к. макрос вообще не порождает код, а функция - порождает.[/uquote]Я же приводил листинг. Где вы там порождение кода увидели? Константа превратилась в другую константу.
[uquote="ARV",url="/forum/viewtopic.php?p=3816695#p3816695"]а в чем еще слабость макроса в упомянутом контектсе?[/uquote]Шо, опять? Снова "этого кто-то не знал" будет?
вы приводили листинг С++ функции, которая в частном случае не привела к порождению кода.
я привел в пример макрос, который делает то же самое, но безусловно всегда (для константного параметра) без порождения кода, причем даже в С
вы утверждаете, что у макроса есть какие-то недостатки
мне не известны эти недостатки, и я прошу вас их реально показать
в отличие от вас, я академиев не кончал, и хочу понять, что же не так в моих познаниях, собранных, в том числе, и из мудрости разных форумов.
что вас бесит-то?
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
[uquote="ARV",url="/forum/viewtopic.php?p=3816770#p3816770"]вы приводили листинг С++ функции,[/uquote]Уберите constexpr и это будет обычная C функция, которая с константным аргументом тоже не будет порождать код.
[uquote="ARV",url="/forum/viewtopic.php?p=3816770#p3816770"]мне не известны эти недостатки, и я прошу вас их реально показать[/uquote]А зачем мне это надо? Чтобы вы опять кинулись минусить сообщения и звать маму (модератора) на помощь?
[uquote="ARV",url="/forum/viewtopic.php?p=3816770#p3816770"]в отличие от вас, я академиев не кончал, и хочу понять, что же не так в моих познаниях, собранных, в том числе, и из мудрости разных форумов.[/uquote]Сами, сами.
[uquote="ARV",url="/forum/viewtopic.php?p=3816770#p3816770"]что вас бесит-то?[/uquote]Хамить изволите? И после этого рассчитываете что вас учить будут? Ну-ну.
VladislavS писал(а):это будет обычная C функция, которая с константным аргументом тоже не будет порождать код
только в том случае, если будет особым образом оформлена и использована ТОЛЬКО с константным аргументом (и то не факт). во всех прочих случаях - будет порождать код.
VladislavS писал(а):И после этого рассчитываете что вас учить будут?
я лишь рассчитываю, что каждый говорящий в состоянии аргументировать свои слова. но если не в состоянии - я умолкаю...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
[uquote="ARV",url="/forum/viewtopic.php?p=3816809#p3816809"]ТОЛЬКО с константным аргументом[/uquote]Да определитесь уже, вам с константным или нет? Мне вот всё равно, функция будет работать в любом случае.
[uquote="ARV",url="/forum/viewtopic.php?p=3816809#p3816809"]во всех прочих случаях - будет порождать код.[/uquote]Во всех прочих случаях макрос в лучшем случае тоже будет попрождать код, а в худшем просто не будет работать (пример я показал), но вам об этом не скажет.
Вопрос только о С, без плюсов.
В очередной раз по новому реализуя конечный автомат, задумался - а кто вообще как делает обычно? Также по ситуации или обычно одно и тоже?
Когда простая прошивка - делаю на свитчах. Когда сложнее, раньше обычно использовал массив структур с переходами, вроде
Но тратится время на поиск перебором. И т.к. эвенты у меня генерились прерываниями, бывали косяки. Потом уже придумал, что эвенты можно из прерываний записывать в некий стек ну или просто временные переменные и уже только лишь в нужно время выдергивать их по одному.
Сейчас вот решил сделать на двумерном массиве, что вроде как шаг назад и менее эффективно. Таблица занимает состояния * эвенты * sizeof(указатель на функцию). Сначала примеры в сети увидел когда на тему таблицы - там зачем-то заполняли все элементы. Не красиво. Подумал - ведь в современном C можно только нужные переходы указать в таблице и все будет также лаконично, как и с массивом стуктур.
Но мне нравится простота реализации. Как-то так в общем виде: Спойлер
eState fsNormalBypass() {
...
}
...
// Transition table type
typedef eState (*trans_t[ST_LAST][EV_LAST])(void);
// Transition table
trans_t trans = {
[ST_NORMAL][EV_BTN_SHORT] = fsNormalBypass,
[ST_NORMAL][EV_BTN_LONG] = fsNormalClosed,
[ST_BYPASS][EV_BTN_SHORT] = fsBypassNormal
...
};
// Get event in order of priority
eEvent fsGetEvent() {
eEvent ret = EV_NONE;
...
return ret;
}
// Run the transition based on event
eRetCode fsTransition() {
#ifdef VERBOSE_LOGS
LOG("Transition: st %d, ev %d\r\n", state.cur_state, state.event);
#endif
if ((state.event < EV_LAST) && trans[state.cur_state][state.event] != NULL) {
state.prev_state = state.cur_state; // save previous state
state.cur_state = trans[state.cur_state][state.event](); // run the transition
return RET_OK;
}
return RET_ERROR;
}
int main(void)
{
...
while(1)
{
state.event = fsGetEvent();
if (state.event != EV_NONE)
fsTransition();
}
}
fsGetEvent() пробегает по "стеку" эвентов и возвращает эвент с наивысшим приоритетом. fsTransition() делает простейшую проверочку и вызывает обработчик просто обратившись к его указателю в адресе 2D массива.
А вы как делаете?
Последний раз редактировалось NStorm Пн апр 13, 2020 18:41:23, всего редактировалось 1 раз.
Когда большинство эвентов из любого состояния требует переход, т.е. таблица по большей части полная - то это вполне оправдано я полагаю.
Тут смотря чем жертвовать. Если без пустот - то тратим циклы на пробежку в поисках.
я как-то исторически организую свою программу не в виде автомата состояний в чистом виде, а именно по событийной модели "эвент - реакция". соответственно, чаще всего именно switch-ем обхожусь.
ваш подход интересный. правда, вынудит меня слишком много думать над тем, чтобы заранее рассчитать все переходы... не привычно...
если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе
при взгляде на многих сверху ничего не меняется...
Переходы также просто добавляют в массив trans[ST_LAST][EV_LAST]. Просто создается функция, делающая переход и возвращающая следующее состояние. А в массиве указатель на неё.
Я наоборот подобный подход решил использовать для простоты расширения и добавления новых состояний и переходов. Потому что когда их становится много, код может стать сложночитаемый, если все переходы в одном месте собраны.
PS: Подход не мой, я его честно "на просторах" подглядел давно еще, только в англоязычной среде. Только как мне удобнее написал.
Последний раз редактировалось NStorm Пн апр 13, 2020 18:41:49, всего редактировалось 1 раз.
Reflector, это к произношению вопрос? ) Я в курсе как оно на английском произносится, но тогда уж скорее всего "ивэнт". А "эвент" это просто англицизм, а не попытка передать звучание английского слова на кириллице )