реклама на сайте
подробности

 
 
> Инкрементирующийся define, c помощью препроцессор Си
Alt.F4
сообщение Jul 10 2016, 06:40
Сообщение #1


Профессионал
*****

Группа: Свой
Сообщений: 1 468
Регистрация: 28-03-10
Из: Беларусь
Пользователь №: 56 256



Здравствуйте.

Написан конечный автомат на конструкции switch - case. Для перехода к последующему действию просто инкрементируется указатель:
Код
switch(i)
{
case 0: ... i++;
case 1: ... i++;
...
case N: ... i++;
}

Действий порядка 100 и возникла проблема с добавлением новых case-обработчиков в середину конструкции, т.к. приходится увеличивать все последующие номера case.

Хочется перенести эту задачу на плечи препроцессора и оформить конструкцию таким образом, чтобы название макроопределения case было у всех одинаковым и, в тоже время, каждое последующее значение было на 1 больше предыдущего:
Код
switch(i)
{
case INCNAME: ... i++;
case INCNAME: ... i++;
...
case INCNAME: ... i++;
}

Подскажите, пожалуйста, возможно ли это как-то реализовать?
Спасибо.
Go to the top of the page
 
+Quote Post
4 страниц V   1 2 3 > »   
Start new topic
Ответов (1 - 14)
adnega
сообщение Jul 10 2016, 06:49
Сообщение #2


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Так получится?
Код
int j = 0;

if(0){}
else if((j++) && (i == j))
{
  // do 1
  i++;
}
else if((j++) && (i == j))
{
  // do 2
  i++;
}
...
else if((j++) && (i == j))
{
  // do N
  i++;
}


Код
#define NEXT else if((j++) && (i==j))

if(0){}
NEXT
{
}
NEXT
{
}
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 07:27
Сообщение #3


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



"В лоб" задача решается применением enum.
CODE
typedef enum
{
      IDLE,
      START,
      RUN,
      STOP
} state_t;

state_t State;


switch (State)
{
case IDLE:
    .....
    State = START;
    break;

case START:
    ....
В середину такого конечного автомата легко добавляется любое количество новых состояний. Конечно, придумать около 100 названий для сотояний и не сорваться на использование цифр в этих названиях - задача непростая.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
jcxz
сообщение Jul 10 2016, 07:30
Сообщение #4


Гуру
******

Группа: Свой
Сообщений: 5 228
Регистрация: 3-07-08
Из: Омск
Пользователь №: 38 713



Цитата(Alt.F4 @ Jul 10 2016, 12:40) *
Действий порядка 100 и возникла проблема с добавлением новых case-обработчиков в середину конструкции, т.к. приходится увеличивать все последующие номера case.
Хочется перенести эту задачу на плечи препроцессора и оформить конструкцию таким образом, чтобы название макроопределения case было у всех одинаковым и, в тоже время, каждое последующее значение было на 1 больше предыдущего:

Значения после case должны быть разными. Иначе компилятор просто не станет компилить.
Я в подобных случаях использую enum. При добавлении хоть в середину хоть в конец нет проблем с перенумерацией.
enum { //фазы автомата состояний
INCNAME_SOST0, INCNAME_SOST1, INCNAME_SOST2, ...};

Цитата(adnega @ Jul 10 2016, 12:49) *
Так получится?
else if((j++) && (i == j))
...

Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".
Go to the top of the page
 
+Quote Post
adnega
сообщение Jul 10 2016, 07:47
Сообщение #5


Гуру
******

Группа: Свой
Сообщений: 2 724
Регистрация: 14-05-07
Из: Ярославль, Россия
Пользователь №: 27 702



Цитата(jcxz @ Jul 10 2016, 10:30) *
Не компилил, но почти уверен, что на такую конструкцию компилятор скажет: "Undefined behavior".

Компилируется даже без предупреждений.
Единственное, в {} не должно быть i++.
Лучше new_i++, а в самом конце i = new_i.
Иначе автомат выстрелит очередью.
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 08:19
Сообщение #6


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(Alt.F4 @ Jul 10 2016, 09:40) *
Подскажите, пожалуйста, возможно ли это как-то реализовать?
Спасибо.

Создаете в Excel одну строку с одним макроопределением.
Потом протягиваете ее до 100 строк и получаете идеальный инкремент.
Если нужно вставить что-то в середину, то в вставляете в Excel-е и снова протягиваете, получите новый инкремент.
Потом Copy-Paste из Excel-а
Прикрепленное изображение


А числа на макросы заменяются автоматически с использованием регулярного выражения.
Go to the top of the page
 
+Quote Post
Владивольт
сообщение Jul 10 2016, 08:38
Сообщение #7


Частый гость
**

Группа: Участник
Сообщений: 168
Регистрация: 14-02-10
Пользователь №: 55 490



Подход с enum, несомненно, правилен.
Однако, при добавлении состояний, потребуется редактировать в двух местах.
Код
#define INCNAME __COUNTER__

Только надо предусмотреть ловушку какую на случай если __COUNTER__ был ранее использован.
https://gcc.gnu.org/onlinedocs/cpp/Common-P...edefined-Macros


--------------------
#define TRUE (4==(2*2))
Go to the top of the page
 
+Quote Post
x893
сообщение Jul 10 2016, 09:03
Сообщение #8


Профессионал
*****

Группа: Свой
Сообщений: 1 333
Регистрация: 27-10-08
Из: Планета Земля
Пользователь №: 41 226



Есть такая реализация, сделана на swich/case и __LINE__
http://dunkels.com/adam/pt/index.html
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2016, 09:49
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



QUOTE (Alt.F4 @ Jul 10 2016, 09:40) *
Действий порядка 100...

Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик sad.gif.
Думайте о комбинации методов. Более-менее типичный выход из такой ситуации это использование наряду с состоянием конечного автомата дополнительных битовых флагов.


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 09:54
Сообщение #10


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(zltigo @ Jul 10 2016, 12:49) *
Что говорит о том, что решение поставленной задачи только с помощью конечного автомата зашло в тупик sad.gif.
Думайте о комбинации методов.

Да нормально, есть прикладные протоколы с очень большими словарями.

Только вот enum для этого негодное средство,
поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.
Go to the top of the page
 
+Quote Post
zltigo
сообщение Jul 10 2016, 10:26
Сообщение #11


Гуру
******

Группа: Свой
Сообщений: 13 372
Регистрация: 27-11-04
Из: Riga, Latvia
Пользователь №: 1 244



Цитата(AlexandrY @ Jul 10 2016, 12:54) *
Да нормально, есть прикладные протоколы с очень большими словарями.

Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус.
Цитата(AlexandrY @ Jul 10 2016, 12:54) *
Только вот enum для этого негодное средство,
поскольку при отладке...

Отладка сколь-нибудь серьезных ПРОТОКОЛОВ отладчиком есть абсолютно непригодное средство, ибо все проблемы взаимодействия оборудования раснообразных производителей начнутся не тогда, когда все лежит на столе.
Так что логирование состояния конечного автомата обязательно, ну а при логировании разворачивание названий состояний в текст так же обязательно. Все это решается через общую функцию изменения состояния автомата. Например:
Код
void q921_set_state( LAPD_t *ldp, ulong new_state  )
{
    ldp->state =  new_state;
    dprintf( "\tL%1X:Set State`%s`(Cmd:%4X)\r", ldp->ch, q2_states[ldp->state], ldp->q921_cmd );
}


--------------------
Feci, quod potui, faciant meliora potentes
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 11:49
Сообщение #12


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(zltigo @ Jul 10 2016, 13:26) *
Не путайте протоколы с их РЕАЛИЗАЦИЕЙ через анус. Сотня состояний конечного автомата это уже анус.
Отладка сколь-нибудь серьезных ПРОТОКОЛОВ отладчиком есть абсолютно непригодное средство, ибо все проблемы взаимодействия оборудования раснообразных производителей начнутся не тогда, когда все лежит на столе.

Прямо сейчас у меня в работе протокол с 41-им case в парсере.

Линейная структура кода позволяет легко его форматировать и рефакторить.
Регулярные выражения замены легче писать под такую структуру кода.
Работает она быстрее.
Короче одни плюсы. biggrin.gif

Протоколы только отладчиком через SWD и можно детально отладить.
Логи для протоколов - это во первых медленно, во вторых менее информативно, в третьих сами вносят нежелательный эффект в виде роста стека задач и ухудшения реалтайма.
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 11:55
Сообщение #13


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (AlexandrY @ Jul 10 2016, 12:54) *
Только вот enum для этого негодное средство,
поскольку при отладке невозможно узнать значение макроса и приходится все равно либо в комментариях либо прямым присваиванием вписывать числа.
Вот этого не понял. Мой отладчик пишет численное значение при помещени указателя мыши на имя. Да и небходимость узнать конкретное значение возникает очень редко, чаще гораздо важнее знать именно имя состояния конечного автомата.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
AlexandrY
сообщение Jul 10 2016, 12:02
Сообщение #14


Ally
******

Группа: Модераторы
Сообщений: 6 232
Регистрация: 19-01-05
Пользователь №: 2 050



Цитата(Сергей Борщ @ Jul 10 2016, 14:55) *
Мой отладчик пишет численное значение при помещени указателя мыши на имя.


Трудно припомнить название? biggrin.gif
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Jul 10 2016, 12:40
Сообщение #15


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (AlexandrY @ Jul 10 2016, 15:02) *
Трудно припомнить название? biggrin.gif
gdb + eclipse.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post

4 страниц V   1 2 3 > » 
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 1st August 2025 - 20:19
Рейтинг@Mail.ru


Страница сгенерированна за 0.01495 секунд с 7
ELECTRONIX ©2004-2016