1. есть некая структура, с несколькими полями (пока они одного типа, но, для общего решения, пусть они будут разнотипные)
2. нужно со всеми полями структуры провести однотипные и, возможно рекурсивные, задачи ("рекурсия_по_полю"), для простоты опишем эту задачу так: - нам прислали ящик яблок - ого! но мы можем съесть за раз только одно - отправляем сами себе же посылку с одним яблоком - ого! нам прислали ящик с одним яблоком, наш размерчик, лопаем, благодарим отправителя, требуем продолжения банкета! - и так, пока не сожрем всю посылку
(конкретика для этой задачи не важна, тема топика дальше)
3. подобные задачи нужно будет сделать со всеми полями структуры по порядку 4. т.к. задачи "однотипные", то вполне логична "рекурсия_по_структуре" 5. можно решить тупо в лоб, написать кучу функций, реализующих обработку каждого поля, и вызывать весь этот паровоз последовательно, один за другим...
но хотелось бы однообразно, получить список ящиков (для каждого поля) и скормить это все за-раз...
т.е. реализовать обработку в одной функции, а к полям обращаться по индексу
далее код, который последовательно приближается к такому решению, но на последнем этапе осталась нерешенная задача по использованию типа в разыменовании, нужно подставлять разные типы.
Я правильно понимаю - хочется одинаково "пройтись" по всей структуре, содержащей разные типы? Ес-но придется в обработчике вручную учитывать типы. На Си. На C++14 пишут можно шаблонами решить органично: https://github.com/CppCon/CppCon2016/bl ... 202016.pdf
На чистом Си для упрощения задачи, чтобы не писать эту кучу разношерстных кастов, можно данные одного типа группировать в массивы внутри структуры. "5 яблок uint8_t, 3 яблока uint16_t и 2 яблока uint32_t".
1. на СИ 2. стуктура внешняя, без изменений (и задача пока решается в общем случае! последний код - есть решение для случая с одношерстыми данными) 3. судя по предложенному коду
Код:
"5 яблок uint8_t, 3 яблока uint16_t и 2 яблока uint32_t".
задачу не совсем поняли...
попробую обьяснить еще раз
1. имеется N полей 2. каждое поле должно "обсчитаться" 3. приходит посылка с "большим количеством яблок" для каждого поля (внешний цикл), (т.е. куча посылок, 1я посылка для поля 1, 2я посылка для поля 2, 3я посылка...) 4. для каждого поля посылка разбивается на посылки с одним яблоком, и вызывает рекурсия "самому себе" 5. и так "разбор" посылок для каждого поля
...
так-то, текущая задача достаточно проста, с одним типом данных и, поэтому, внешний цикл вызовов уже реализован (тот самый последний код)
просто, для тренировки усов, лап и хвостов... решил потренироваться "на разношерстных котах"
ну ... т.е. пока не вижу решения ... или уточните ваши идеи
спасибо
_________________ Енот - это кот, только инкогнито! p.s. держитесь обоими руками, а то прорвет...
Давайте без яблок. Я выше написал - "Я правильно понимаю - хочется одинаково "пройтись" по всей структуре, содержащей разные типы?" - это так? Если так, то ответ там уже был дан. На чистом Си невозможно пройтись итеративно по всей структуре с разными типами данных, не описывая в коде логику работы с этими типами данных. Т.е. как бы универсально написать так, что скажем к каждому элементу структуры прибавлялось бы 1, внезависимости от размерности и типов данных структуры - не получится. Логика кода ("внешний цикл") должен знать, с чем он работает. Как альтернативу, для упрощения написания этой логики, я предложил группировать данные в структуре по типам.
Обязательным условием долгой и стабильной работы Li-FePO4-аккумуляторов, в том числе и производства EVE Energy, является применение специализированных BMS-микросхем. Литий-железофосфатные АКБ отличаются такими характеристиками, как высокая многократность циклов заряда-разряда, безопасность, возможность быстрой зарядки, устойчивость к буферному режиму работы и приемлемая стоимость. Но для этих АКБ очень важен контроль процесса заряда и разряда для избегания воздействия внешнего зарядного напряжения после достижения 100% заряда. Инженеры КОМПЭЛ подготовили список таких решений от разных производителей.
в GCC есть макрос offsetof, который позволяет обратиться к полю структуре по смещению этого поля, зная начало структуры. т.е. не по имени поля обращаться, а по его относительному адресу в памяти. таким образом, можно в функцию передавать значение этого макроса и внутри функции абсолютно однотипно обсчитывать любые поля.
я верно понял, что вы хотите?
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
Компания EVE выпустила новый аккумулятор серии PLM, сочетающий в себе высокую безопасность, длительный срок службы, широкий температурный диапазон и высокую токоотдачу даже при отрицательной температуре.
Эти аккумуляторы поддерживают заряд при температуре от -40/-20°С (сниженным значением тока), безопасны (не воспламеняются и не взрываются) при механическом повреждении (протыкание и сдавливание), устойчивы к вибрации. Они могут применяться как для автотранспорта (трекеры, маячки, сигнализация), так и для промышленных устройств мониторинга, IoT-устройств.
внезависимости от размерности и типов данных структуры - не получится
-> если опустить некоторые моменты не совсем красиво, но все в одном месте, уже и это плюс
Код:
... // var.4 доступ к "разношерстным" данным через индекс ... switch(i) { case 0 : p_void = ( ((void*)p_void) + shift ); *( (uint8_t *)p_void) = ((i+1)*10); break; case 1 : p_void = ( ((void*)p_void) + shift ); *( (uint16_t *)p_void) = ((i+1)*10); break; case 2 : p_void = ( ((void*)p_void) + shift ); *( (uint32_t *)p_void) = ((i+1)*10); break; }
...
to ARV
Цитата:
...обратиться к полю структуре по смещению этого поля, зная начало структуры. т.е. не по имени поля обращаться, а по его относительному адресу в памяти...
так и сделано
Цитата:
в GCC есть макрос offsetof + таким образом, можно в функцию передавать значение этого макроса и внутри функции абсолютно однотипно обсчитывать любые поля.
вот с этим можно поразбираться...(а код выше, хоть и раздутый, но делает то, что надо)
Цитата:
внутри функции абсолютно однотипно обсчитывать любые поля
с макросом еще не разбирался, с помощью него обращение к полям через индекс?
is a suitable definition of the offsetof macro. In C++, type may be dependent. In either case, member may consist of a single identifier, or a sequence of member accesses and array references.
...
гм.. эге... мур... не, бля, точно муррр... я столько не выкурю придется почитать, что пишут по этому поводу бывалые коты и фугля... мугля ... гугля... да, точно гугля!
зы: спасибо
_________________ Енот - это кот, только инкогнито! p.s. держитесь обоими руками, а то прорвет...
Какая то нереальная задача. Каждая структура обрабатывается соответственно. Хоть полями, хоть кусочками байтами. Универсальности нет. И не выдумывайте лишнего.
Ничего нового не увидел. И вы только что своими руками доказали, универсальности нет. Свитч кейс, кстати, первое, что мне в голову пришло. Сам так делал неоднократно. Но с индексом не заморачивался. Выхлоп больше получается.
все универсальные решения на поверку оказываютс во-первых, не универсальными, а во-вторых, громоздкими. что касается доступа к полям структуры по индексу, т.е. по номеру поля, то напрашивается следующее универсальное решение 1. обращаться будем при помощи "универсальной" функции
Код:
void something(const field id, void *rec, rec_type *rectype){ int32_t field; // сюда поместим значение поля field = rectype[id].func(rec + rectype[id].offset); // дальше делаем с этим field то, что нужно }
первый параметр - номер поля, второй - адрес структуры, третий - адрес массива, в котором описаны поля этой структуры 2. поля структуры описываются так:
Код:
typedef int32_t (value*)(void*); // тип описания функции, возвращающей значение поля typedef struct{ uint8_t offset; // смещение пол относительно начала структуры value func; // функция, которая вернет значение поля } rec_type;
3. создаем функции для полей разных типов. и тут первая проблема "универсальности" - только целочисленные значения могут быть возвращены. float, например, уже не укладывается в концепцию.
Код:
int32_t get_byte(char *ptr){ return *ptr; }
int32_t get_int(int *ptr){ return *ptr; } // и так далее для всех вариантов полей, которые могут быть приведены к целочисленному значению
4. создаем и инициализируем массивы описаний разных структур, делая такми способом заготовки для обращения по индексу. 5. ну, а далее - обращаемся к полям по индексам...
все это давным давно реализовано в С++, т.к. по сути является именно сишной реализацией подобия таблиц виртуальных методов... но всё это хуже, чем С++, поскольку - см. выше, - имеет ограничения по "универсальности". и, как видите, реализация тоже не очень краткая и не очень удобная - см. начало моего поста - вторая проблема "универсальности".
мой опыт программирования позволяет мне утверждать, что выход тут только один - отказаться от НЕНУЖНОЙ универсальности, т.е. переформулировать задание и/или алгоритм так, чтобы необходимости в такой "универсальности" не возникало.
_________________ если рассматривать человека снизу, покажется, что мозг у него глубоко в жопе при взгляде на многих сверху ничего не меняется...
- нам прислали ящик яблок - ого! но мы можем съесть за раз только одно - отправляем сами себе же посылку с одним яблоком - ого! нам прислали ящик с одним яблоком, наш размерчик, лопаем, благодарим отправителя, требуем продолжения банкета! - и так, пока не сожрем всю посылку
с макросом еще не разбирался, с помощью него обращение к полям через индекс?
Непонятно, зачем вы заостряете внимание на каком-то "обращении через индекс". Обращение через индекс, то есть определение положения очередного поля в памяти, никакого труда не представляет и легко реализуется через таблицу смещений с помощью того же `offsetof` (которое есть не "в GCC", как тут сбивающе с толку написали, а является хрестоматийной классикой стандартного языка С, то есть к GCC как таковому не имеет никакого отношения вообще).
Проблема то не в "обращении по индексу". Проблема в том, что каждое поле может иметь свой тип и требовать своей собственной обработки. Тут, очевидно, можно выкрутиться через таблицу обработчиков, принимающих `void *` и уже внутри знающих, что делать со своими полями и какой тип они имеют.
... Тут, очевидно, можно выкрутиться через таблицу обработчиков, принимающих `void *` и уже внутри знающих, что делать со своими полями и какой тип они имеют...
так и сделано, только проще и нагляднее
_________________ Енот - это кот, только инкогнито! p.s. держитесь обоими руками, а то прорвет...
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 39
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения