|
Поиск по массиву в compile time на С |
|
|
|
May 3 2018, 11:54
|
Местный
  
Группа: Участник
Сообщений: 421
Регистрация: 2-01-08
Пользователь №: 33 778

|
Есть массив регистров, ссылки на переменные с именами и некоторыми параметрами, для удобного доступа по разным интерфейсам и конфигурирования устройства. Допустим вот так объявленный, Код typedef struct {
const char *sym;
const char *fmt; int mode;
union {
float *f; int *i; } link;
void (* proc) (const void *reg, void *lval, const void *rval); } reg_t;
#define REG_E(link, extra, unit, fmt, mode, proc) { #link extra "\0" unit, fmt, mode, \ { (void *) &link }, (void *) proc }
#define REG(link, unit, fmt, mode, proc) REG_E(link, "", unit, fmt, mode, proc)
const reg_t regfile[] = {
REG(hal.USART_baud_rate, "", "%i", REG_CONFIG, NULL), REG(hal.PWM_freq_hz, "Hz", "%i", REG_CONFIG, NULL), REG(hal.PWM_dead_time_ns, "ns", "%i", REG_CONFIG, NULL), REG(hal.ADC_reference_voltage, "V", "%3f", REG_CONFIG, NULL), REG(hal.ADC_current_shunt_resistance, "Ohm", "%4e", REG_CONFIG, NULL), ... REG(pm.probe_speed_ramp, "rad/s", "%2f", REG_CONFIG, NULL), REG_E(pm.probe_speed_ramp, "_rpm", "rpm", "%2f", REG_NORMAL, ®_proc_rpm), ... Регистры адресуются по именам или по номерам. Имена достаточно постоянны, а номера могут изменяться в следующих версиях. В этом проблема, нельзя в коде просто взять ссылку на регистр по номеру regfile[n], номер может измениться. Искать по имени в compile time слишком сложно, средствами C и препроцессора не обойтись. По адресам переменных нельзя, они могут повторятся. Какие еще варианты? Сейчас думаю, генерировать из объявления массив макросов вида #define REG_hal_USART_baud_rate 0, но здесь тоже много проблем, надо как-то "спасать" недопустимые символы (точка и др.). Да можно обратится к переменным напрямую, но в некоторых случаях надо например сделать вывод значений, а в этом массиве регистров уже есть информация о том как это сделать для данного параметра. Не хочется дублировать одно и тоже в разным местах. Спасибо.
|
|
|
|
|
 |
Ответов
|
Aug 13 2018, 17:36
|
Гуру
     
Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493

|
Вот чтобы не плодить тем, возник вопрос. Есть структура в вижуал студио. Ее поля имеют тип enum. Эта структура необходима для сериализации по юарту. Заниматься разборкой каждого поля, или, особо извращённым способом, делать каждое поле методом, пишущим себя в выходной поток нет ни желания, ни необходимости. Поэтому аккуратно подставив pragma pack попробовал. Все замечательно, но вот студия считает, что поля типа моего enum имеют тип int, обьявление у меня простое, по шариковски, typedef emum {Eins ,Zwei, Polizei} eMytype; А вот GCC решил, что такой тип прекрасно ложится в чар, на что имеет право Цитата Each enumeration defines a type that is different from all other types. Each enumeration also has an underlying type. The underlying type can be explicitly specified using enum-base; if not explicitly specified, the underlying type of a scoped enumeration type is int. In these cases, the underlying type is said to be fixed. Following the closing brace of an num-specifier, each enumerator has the type of its enumeration. (хотя мой инглиш слаб, и может и не имеет). Теперь мысли что делать. В с++ с типами строже, отказываться от типа энум не хочу, там это ошибка, причем полезная. Можно сделать как typedef emum {Eins ,Zwei, Polizei, empty = 0xffffff}, в Гцц, тогда он сделает энумы интом, но это тоже так себе идея, тем более скорее хотелось бы пыл студии усмирить на предмет делать все это интом. Третий вариант в студии enum class eMytype : char {Eins ,Zwei, Polizei} сделать, но тогда не совсем понял как юзать старый трюк в С с " {Eins ,Zwei, Polize, max_enum_elents}, max_enum_elents будет строго типизировано и пробежаться по его его варинтам вплоть до него "по индексу" не выйдет. Цитата(Nixon @ Aug 13 2018, 16:58)  Для доступа по индексу можно так сделать Код enum VARIABLES { VAR1, VAR2, ... VARN, VAR_MAX }; описание списка переменных Код const TVAR VarArray[VAR_MAX] = { [VAR1] = <тут ваша реализация>, [VAR2] = <тут ваша реализация>, ... [VARN] = <тут ваша реализация> }; собственно ваш реестр инициализации. Обращение к реестру можно делать по индексу (0-N) или по имени (VAR1-VARN). Симпатично, жаль это since C99, поэтому не так много где описано и использовано. Буду знать.
|
|
|
|
|
Aug 13 2018, 18:31
|

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

|
QUOTE (DASM @ Aug 13 2018, 20:36)  max_enum_elents будет строго типизировано и пробежаться по его его варинтам вплоть до него "по индексу" не выйдет. Явное приведение типа все еще работает. for(uint_fast8_t i = 0;i < uint_fast8_t(eMytype::max_enum_elents); ++i)/ QUOTE (DASM @ Aug 13 2018, 20:36)  Симпатично, жаль это since C99 18 лет, уже не девочка...
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 13 2018, 19:47
|

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

|
QUOTE (DASM @ Aug 13 2018, 21:37)  да оно и неявно сработает, и в этом случае без enum class "eMytype::max_enum_elents" будет лишним Неявно сработает только в случае простого enum. В случае enum class нужно явное приведение и "eMytype::max_enum_elents" тоже будет нужно. QUOTE (DASM @ Aug 13 2018, 21:37)  Но как enum сделать гарантированно char ами? enum class eMytype : uint8_t {}. И еще: char, signed char и unsigned char - три разных типа, поэтому "голый" char нужно использовать только для хранения символов. Для чисел нужно использовать signed char и unsigned char, а еще лучше (u)uint8_t. Если бы у вас был enum eMytype { '1', '2', '3' } - вот тогда бы я к char не придирался.
--------------------
На любой вопрос даю любой ответ"Write code that is guaranteed to work, not code that doesn’t seem to break" ( C++ FAQ)
|
|
|
|
|
Aug 13 2018, 20:08
|
Гуру
     
Группа: Свой
Сообщений: 3 644
Регистрация: 28-05-05
Пользователь №: 5 493

|
Цитата(Сергей Борщ @ Aug 13 2018, 22:47)  Неявно сработает только в случае простого enum. В случае enum class нужно явное приведение и "eMytype::max_enum_elents" тоже будет нужно. enum class eMytype : uint8_t {}.
И еще: char, signed char и unsigned char - три разных типа, поэтому "голый" char нужно использовать только для хранения символов. Для чисел нужно использовать signed char и unsigned char, а еще лучше (u)uint8_t. Если бы у вас был enum eMytype { '1', '2', '3' } - вот тогда бы я к char не придирался. Какие придирки? Так я и спрашиваю, как сделать перечисление, где каждый элемент это char? Выше выяснили, что так вот просто через enum компиляторонезависимо не выйдет. Завтра поиграю с юнионом по совету. Цитата(Forger @ Aug 13 2018, 22:49)  Command - НЕ глобальная переменная, а статическая константа, которую, кстати, надо будет сделать constexpr.... Вообще, в данном примере показан бут-загручик (!) в одном из старых проектов, а эта структура Command используется прямо внутри соотв. cpp файла. Сам набор эти команд (Command) имеет смысл делать видимым только внутри этого модуля (в данном случае он называется Communication). Чтобы не загромождать соотв hpp файл никому не нужным снаружи этим набором команд, то они просто добавлены внутри соотв. cpp файла и им приписано static. По сути эта const struct - замена enum, видимая только внутри cpp файла, но позволяющая более легко читать текст, благодаря разбиения на поля и подструктуры.
Впрочем, в данный момент, глядя на эти исходники, некоторые мелочи я бы сделал иначе. ... Но суть не в этом, а в том, что пример я привел для того, чтобы показать как можно обойтись без enion вообще. Да не замена это. Энум нигде не хранится, просто объявление. Можно сделать его на пару миилиардов элементов, а при использовании поле его займет 4 байта. С const struct несколько не то. Надо ещё подумать
|
|
|
|
Сообщений в этой теме
amaora Поиск по массиву в compile time на С May 3 2018, 11:54 Kabdim А зачем так сделано? Выглядит как кусок для внешне... May 3 2018, 12:09 Forger Масло-масляное.
Ваш некий реестр (я так понял по н... May 3 2018, 12:15 x736C Цитата(Forger @ May 3 2018, 15:15) зы. А ... May 3 2018, 14:01  Forger Цитата(x736C @ May 3 2018, 17:01) Как при... May 3 2018, 14:42 jcxz Цитата(Forger @ May 3 2018, 15:15) В свои... May 5 2018, 09:33  Forger Цитата(jcxz @ May 5 2018, 12:33) Лучше ра... May 5 2018, 10:26   jcxz Цитата(Forger @ May 5 2018, 13:26) К тому... May 5 2018, 11:02    Forger Цитата(jcxz @ May 5 2018, 14:02) Вобщем -... May 5 2018, 14:50 amaora Параметры не константные, все разные, есть настрой... May 3 2018, 13:16 Kabdim А точка в ваших определениях регистров всегда буде... May 3 2018, 13:40 amaora Функции доступа я тоже мог бы написать, но в этом ... May 5 2018, 08:15 amaora Вот так сделал
Кодcat regfile.c | sed -n ... Aug 11 2018, 18:54 Arlleex Цитата(amaora @ Aug 11 2018, 21:54) Вот т... Aug 12 2018, 07:00 amaora Ну, здесь я обычно не задаю вопросов по своей осно... Aug 12 2018, 16:52 Nixon Для доступа по индексу можно так сделать
Кодenum V... Aug 13 2018, 13:58 Forger Цитата(Nixon @ Aug 13 2018, 16:58) Для до... Aug 13 2018, 14:51 Forger Цитата(DASM @ Aug 13 2018, 20:11) ...
Пыт... Aug 13 2018, 17:39   Forger Цитата(DASM @ Aug 13 2018, 21:37) Но как ... Aug 13 2018, 18:39     Forger Цитата(DASM @ Aug 13 2018, 23:08) Можно с... Aug 13 2018, 20:17      Nixon Цитата(Сергей Борщ @ Aug 14 2018, 01:49) ... Aug 14 2018, 06:14       DASM Цитата(Nixon @ Aug 14 2018, 09:14) Не обя... Aug 14 2018, 06:18        Nixon Цитата(DASM @ Aug 14 2018, 09:18) О, кста... Aug 14 2018, 06:24 DASM А наоборот как ?
Кодtypedef enum {t1, t2, t3 = ... Aug 13 2018, 18:15 Forger По-ходу я ошибся с явным указанием типа enum, у ме... Aug 13 2018, 18:25  DASM Цитата(Forger @ Aug 13 2018, 21:25) По-хо... Aug 13 2018, 18:43   Forger Цитата(DASM @ Aug 13 2018, 21:43) А вот т... Aug 13 2018, 19:28 DASM Гы, const struct а тут мы возвращаемся к вопросу и... Aug 13 2018, 19:39 Forger Цитата(DASM @ Aug 13 2018, 22:39) Гы, con... Aug 13 2018, 19:49 Nixon Может ещё кому полезно будет:
В анонимных структу... Aug 13 2018, 20:31 Forger Цитата(Nixon @ Aug 13 2018, 23:31) Наприм... Aug 13 2018, 20:37 Nixon Я без привязки к вашему примеру. Просто довольно п... Aug 13 2018, 20:49 Forger Цитата(Nixon @ Aug 13 2018, 23:49) Просто... Aug 13 2018, 20:51 DASM Вот нашел ответ, как удобно пользовать enum class.... Aug 14 2018, 05:53 Kabdim По факту тип указанный в энуме, года 3 назад работ... Aug 14 2018, 06:32 DASM Да, лучше. Но пока не знал об этом - много писанин... Aug 14 2018, 06:34 Kabdim Цитата(DASM @ Aug 14 2018, 09:34) "3... Aug 14 2018, 06:49 Nixon В стандарте то стандарте, но не совсем "С... Aug 14 2018, 06:39 DASM Цитата(Nixon @ Aug 14 2018, 09:39) В стан... Aug 14 2018, 07:10  Kabdim Цитата(DASM @ Aug 14 2018, 10:10) это как... Aug 14 2018, 07:17 DASM Цитатаtypedef enum { tst, tst2, tst3 } test;
#pra... Aug 16 2018, 06:32 Kabdim Цитата(DASM @ Aug 16 2018, 09:32) А что т... Aug 16 2018, 14:29  DASM Цитата(Kabdim @ Aug 16 2018, 17:29) А чег... Aug 16 2018, 14:41   Forger После sizeof ( некого enum ), недалеко и до sizeof... Aug 16 2018, 14:56    DASM Цитата(Forger @ Aug 16 2018, 17:56) После... Aug 16 2018, 15:09     Forger Цитата(DASM @ Aug 16 2018, 18:09) А все ж... Aug 16 2018, 15:13   Kabdim Цитата(DASM @ Aug 16 2018, 17:41) Просто ... Aug 17 2018, 10:39    Arlleex Цитата(Kabdim @ Aug 17 2018, 14:39) Как э... Aug 17 2018, 10:54    DASM Цитата(Kabdim @ Aug 17 2018, 13:39) Как э... Aug 17 2018, 12:04     Forger Цитата(DASM @ Aug 17 2018, 15:04) offseto... Aug 17 2018, 12:23     Kabdim Применительно к этой ситуации, как раз Кейл - непр... Aug 17 2018, 12:45 sigmaN Извиняюсь, если это уже предлагали(не читал все со... Aug 17 2018, 08:08 Kabdim Я не вижу. Вопрос был DASM'у цитата к которой ... Aug 17 2018, 11:51 sigmaN From Standard C++ 7.2/5:
ЦитатаThe underlying type... Aug 19 2018, 06:25 DASM Да ладно, фиг с ним. Aug 19 2018, 20:41
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|