Если ваш вопрос не влез ни в одну из вышеперечисленных тем, вам сюда.
Ответить

Re: Вопросы по С/С++ (СИ)

Сб мар 21, 2020 16:58:56

arkhnchul писал(а):constexpr-ы обычно лаконичнее и понятнее развесистых макросов
Код:
#define bitrev(x) (((x) & 0x01 ? 0x80 : 0) | \
         ((x) & 0x02 ? 0x40 : 0) | \
         ((x) & 0x04 ? 0x20 : 0) | \
         ((x) & 0x08 ? 0x10 : 0) | \
         ((x) & 0x10 ? 0x08 : 0) | \
         ((x) & 0x20 ? 0x04 : 0) | \
         ((x) & 0x40 ? 0x02 : 0) | \
         ((x) & 0x80 ? 0x01 : 0))
по-моему, и лаконичность, и понятность не пострадала в данном случае

Re: Вопросы по С/С++ (СИ)

Сб мар 21, 2020 17:03:39

В коде писать
Код:
tmp = bitrev((3<<A)|(4<<B)|(5<<C))
?

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 09:56:56

по-моему, и лаконичность, и понятность не пострадала в данном случае
Да причём тут лаконичность? Мне на неё положить - один раз написал и забыл. Подумай, какой код даст твой макрос на вот таком простом коде
Код:
*(volatile uint8_t *)&SPI1->DR = bitrev(SPI1->DR);

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 10:06:10

А че тут думать, если вы приводите пример run-time, а речь шла о вычислениях compile-time? То есть выражение-параметр макроса у вас не константа?

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 10:16:01

Функция, в отличии от макроса, работает и в компайлтайме, и в рантайме.

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 11:17:51

А кто-то этого не знал? Речь шла о том, как реверсировать константы, для этого функция не обязательна. Тем более что увеличивает объём кода.

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 11:32:05

А кто-то этого не знал?
Получается, что нет. Иначе зачем спрашивать было?
Почему? Или чем хужее?


Речь шла о том, как реверсировать константы, для этого функция не обязательна.
Я это в первом же ответе написал. Что можно макросом или функцией.
Тем более что увеличивает объём кода.
Функция как раз таки уменьшает размер кода.

PS: Это, кстати, было не единственное слабое место макроса.

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 14:35:45

VladislavS писал(а):Это, кстати, было не единственное слабое место макроса
так я и спрашиваю о слабостях.


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

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 15:29:22

в контексте вопроса о константных вычислениях функция проигрывает полностью по размеру кода, т.к. макрос вообще не порождает код, а функция - порождает.
Я же приводил листинг. Где вы там порождение кода увидели? Константа превратилась в другую константу.

а в чем еще слабость макроса в упомянутом контектсе?
Шо, опять? Снова "этого кто-то не знал" будет?

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 16:38:30

VladislavS писал(а):Я же приводил листинг
вы приводили листинг С++ функции, которая в частном случае не привела к порождению кода.
я привел в пример макрос, который делает то же самое, но безусловно всегда (для константного параметра) без порождения кода, причем даже в С
вы утверждаете, что у макроса есть какие-то недостатки
мне не известны эти недостатки, и я прошу вас их реально показать
в отличие от вас, я академиев не кончал, и хочу понять, что же не так в моих познаниях, собранных, в том числе, и из мудрости разных форумов.
что вас бесит-то?

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 17:06:53

вы приводили листинг С++ функции,
Уберите constexpr и это будет обычная C функция, которая с константным аргументом тоже не будет порождать код.
мне не известны эти недостатки, и я прошу вас их реально показать
А зачем мне это надо? Чтобы вы опять кинулись минусить сообщения и звать маму (модератора) на помощь?
в отличие от вас, я академиев не кончал, и хочу понять, что же не так в моих познаниях, собранных, в том числе, и из мудрости разных форумов.
Сами, сами.
что вас бесит-то?
Хамить изволите? И после этого рассчитываете что вас учить будут? Ну-ну.

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 17:19:17

VladislavS писал(а):это будет обычная C функция, которая с константным аргументом тоже не будет порождать код
только в том случае, если будет особым образом оформлена и использована ТОЛЬКО с константным аргументом (и то не факт). во всех прочих случаях - будет порождать код.
VladislavS писал(а):И после этого рассчитываете что вас учить будут?
я лишь рассчитываю, что каждый говорящий в состоянии аргументировать свои слова. но если не в состоянии - я умолкаю...

Re: Вопросы по С/С++ (СИ)

Вс мар 22, 2020 17:33:03

ТОЛЬКО с константным аргументом
Да определитесь уже, вам с константным или нет? Мне вот всё равно, функция будет работать в любом случае.
во всех прочих случаях - будет порождать код.
Во всех прочих случаях макрос в лучшем случае тоже будет попрождать код, а в худшем просто не будет работать (пример я показал), но вам об этом не скажет.

Re: Вопросы по С/С++ (СИ)

Вс апр 12, 2020 20:55:59

Вопрос только о С, без плюсов.
В очередной раз по новому реализуя конечный автомат, задумался - а кто вообще как делает обычно? Также по ситуации или обычно одно и тоже?
Когда простая прошивка - делаю на свитчах. Когда сложнее, раньше обычно использовал массив структур с переходами, вроде
Код:
{STATE1, EVENT1, handler_1},
{STATE1, EVENT1, handler_2},
{STATE2, EVENT2, handler_3}


Но тратится время на поиск перебором. И т.к. эвенты у меня генерились прерываниями, бывали косяки. Потом уже придумал, что эвенты можно из прерываний записывать в некий стек ну или просто временные переменные и уже только лишь в нужно время выдергивать их по одному.
Сейчас вот решил сделать на двумерном массиве, что вроде как шаг назад и менее эффективно. Таблица занимает состояния * эвенты * 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 раз.

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 04:39:16

но ведь двумерная таблица с ваших же слов содержит много пустот... разве это "оптимально"?

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 04:46:24

Когда большинство эвентов из любого состояния требует переход, т.е. таблица по большей части полная - то это вполне оправдано я полагаю.
Тут смотря чем жертвовать. Если без пустот - то тратим циклы на пробежку в поисках.

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 05:15:41

я как-то исторически организую свою программу не в виде автомата состояний в чистом виде, а именно по событийной модели "эвент - реакция". соответственно, чаще всего именно switch-ем обхожусь.
ваш подход интересный. правда, вынудит меня слишком много думать над тем, чтобы заранее рассчитать все переходы... не привычно...

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 05:52:18

Так не надо заранее. Можно в процессе добавлять. Состояния и эвенты в любое время добавлять можно. Это просто enum, для именования. Для примера:
Код:
typedef enum {ST_NONE, ST_IDLE, ST_CALIBRATION, ST_NORMAL, ST_BYPASS, ST_OVERFLOW, ST_RESTORATION, ST_MAINTAINCE, ST_LAST} eState;
typedef enum {EV_NONE, EV_BTN_SHORT, EV_BTN_LONG, EV_BAT_LOW, EV_AC_SHORTAGE, EV_TIMEOUT, EV_LAST} eEvent;

Переходы также просто добавляют в массив trans[ST_LAST][EV_LAST]. Просто создается функция, делающая переход и возвращающая следующее состояние. А в массиве указатель на неё.

Я наоборот подобный подход решил использовать для простоты расширения и добавления новых состояний и переходов. Потому что когда их становится много, код может стать сложночитаемый, если все переходы в одном месте собраны.

PS: Подход не мой, я его честно "на просторах" подглядел давно еще, только в англоязычной среде. Только как мне удобнее написал.
Последний раз редактировалось NStorm Пн апр 13, 2020 18:41:49, всего редактировалось 1 раз.

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 06:21:00

Состояния и эвенты

Только ивенты. Хедеры и ивенты, а не наоборот :)

Re: Вопросы по С/С++ (СИ)

Пн апр 13, 2020 06:39:42

Reflector, это к произношению вопрос? ) Я в курсе как оно на английском произносится, но тогда уж скорее всего "ивэнт". А "эвент" это просто англицизм, а не попытка передать звучание английского слова на кириллице )
Ответить