краткое описание задачи:
1. есть некая структура, с несколькими полями (пока они одного типа, но, для общего решения, пусть они будут разнотипные)
2. нужно со всеми полями структуры провести однотипные и, возможно рекурсивные, задачи ("рекурсия_по_полю"), для простоты опишем эту задачу так:
- нам прислали ящик яблок
- ого! но мы можем съесть за раз только одно
- отправляем сами себе же посылку с одним яблоком
- ого! нам прислали ящик с одним яблоком, наш размерчик, лопаем, благодарим отправителя, требуем продолжения банкета!
- и так, пока не сожрем всю посылку
(конкретика для этой задачи не важна, тема топика дальше)
3. подобные задачи нужно будет сделать со всеми полями структуры по порядку
4. т.к. задачи "однотипные", то вполне логична "рекурсия_по_структуре"
5. можно решить тупо в лоб, написать кучу функций, реализующих обработку каждого поля, и вызывать весь этот паровоз последовательно, один за другим...
но хотелось бы однообразно, получить список ящиков (для каждого поля) и скормить это все за-раз...
т.е. реализовать обработку в одной функции, а к полям обращаться по индексу
далее код, который последовательно приближается к такому решению, но на последнем этапе осталась нерешенная задача по использованию типа в разыменовании, нужно подставлять разные типы.
Код: Выделить всё
p_void = ( ((void*)p_void) + shift ); *( (uint8_t *)p_void) = ((i+1)*10); // i-й элементКод: Выделить всё
(uint8_t *)p_void)ну... кидайтесь помидорами, идеями, мымслями
спасибо
Код: Выделить всё
avr-gcc, С-only, linux, etc...
Код: Выделить всё
#include <util/delay.h>
#include "main.h"
#include "lib/prn.h" // prn-lib()
#define SIZE_STRUCT 3
#define SIZE_8 1 // (sizeof int8_t ) // не нашел набегом...
#define SIZE_16 2 // (sizeof int16_t)
#define SIZE_32 4 // (sizeof int32_t)
uint8_t size[SIZE_STRUCT] = {SIZE_8, SIZE_16, SIZE_32};
typedef struct
{
uint8_t a;
uint16_t b;
uint32_t c;
} t;
typedef t* p;
t test ; // экземпляр структуры
p p_test; // указатель на структуру
////////////////////////////////////////////////////////////////////////////////
void prn_struct(int8_t i)
////////////////////////////////////////////////////////////////////////////////
{
prn("--- %i \n", i);
prn("test.a = %u \n", test.a);
prn("test.b = %u \n", test.b);
prn("test.c = %lu\n", test.c);
}
////////////////////////////////////////////////////////////////////////////////
int main(void)
////////////////////////////////////////////////////////////////////////////////
{
void* p_void;
prn_init();
prn("### struct ###\n");
p_test = &test;
p_test->a = 1;
p_test->b = 2;
p_test->c = 3;
prn_struct(1);
/*/
// var.1 доступ к "одношерстным" данным
//
*(((uint8_t*)p_test) + 0) = 4;
*(((uint8_t*)p_test) + 1) = 5;
*(((uint8_t*)p_test) + 2) = 6;
prn_struct(2); //*/
//
// var.2 доступ к "разношерстным" данным
//
*( (uint8_t *) (((void*)p_test) ) ) = 4; // 1й элемент
*( (uint16_t*) (((void*)p_test) + sizeof(uint8_t) ) ) = 5; // 2й элемент
*( (uint32_t*) (((void*)p_test) + sizeof(uint8_t) + sizeof(uint16_t)) ) = 6; // 3й элемент
prn_struct(3); //*/
//
// var.3 доступ к "разношерстным" данным
//
p_void = (((void*)p_test));
p_void = (((void*)p_void) ); *( (uint8_t *)p_void) = 7; // 1й элемент
p_void = (((void*)p_void) + sizeof(uint8_t )); *( (uint16_t *)p_void) = 8; // 2й элемент
p_void = (((void*)p_void) + sizeof(uint16_t)); *( (uint32_t *)p_void) = 9; // 3й элемент
prn_struct(4); //*/
//
// var.4 доступ к "разношерстным" данным через индекс
//
int8_t i, shift;
p_void = (((void*)p_test));
for(i=0; i<3; i++)
{
if(i<=0) { shift = 0 ; } // реализация сдвига
else { shift = size[i-1]; }
p_void = ( ((void*)p_void) + shift ); *( (uint8_t *)p_void) = ((i+1)*10); // i-й элемент
}
prn_struct(5); //*/
return 0;
}
////////////////////////////////////////////////////////////////////////////////
для "одношерстных" данных можно упростить
Код: Выделить всё
for(i=0; i<3; i++)
{
*( (uint8_t*) (((void*)p_test) + i) ) = ((i+1)*10+6); // i-й элемент
}
p.s. держитесь обоими руками, а то прорвет...


