Пт фев 12, 2021 08:53:27
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-й элемент
}
Пт фев 12, 2021 10:04:04
Пт фев 12, 2021 10:41:20
"5 яблок uint8_t, 3 яблока uint16_t и 2 яблока uint32_t".
Пт фев 12, 2021 12:03:00
Пт фев 12, 2021 12:47:14
Пт фев 12, 2021 13:00:54
внезависимости от размерности и типов данных структуры - не получится
...
// 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;
}
...обратиться к полю структуре по смещению этого поля, зная начало структуры. т.е. не по имени поля обращаться, а по его относительному адресу в памяти...
в GCC есть макрос offsetof + таким образом, можно в функцию передавать значение этого макроса и внутри функции абсолютно однотипно обсчитывать любые поля.
внутри функции абсолютно однотипно обсчитывать любые поля
primary:
"__builtin_offsetof" "(" typename "," offsetof_member_designator ")"
offsetof_member_designator:
identifier
| offsetof_member_designator "." identifier
| offsetof_member_designator "[" expr "]"
#define offsetof(type, member) __builtin_offsetof (type, member)
Сб фев 13, 2021 06:32:32
Сб фев 13, 2021 08:00:49
я так понимаю, "массив_типов" создать не получиться :о)
struct types{
uint8_t _t0;
uint16_t _t1;
uint32_t _t2;
};
#define TYPE(n) typeof(types._t##n)
//
// var.4 через индекс / switch (mod)
//
p_void = (((void*)p_test));
for(i=0; i<3; i++)
{
switch(i) // выбор, по "соответствующему типу"
{
case 0 : *( (uint8_t *)p_void) = (256-1 ); break;
case 1 : *( (uint16_t *)p_void) = (65536-1 ); break;
case 2 : *( (uint32_t *)p_void) = (4294967296-1); break;
}
p_void = ( ((void*)p_void) + size[i] ); // сдвиг указателя "с опозданием" (то, что нужно :о)
}
prn_struct(4); //*/
Сб фев 13, 2021 12:14:13
Сб фев 13, 2021 17:28:56
Ничего нового не увидел
#define TYPE(n) ...
Вс фев 14, 2021 12:06:01
void something(const field id, void *rec, rec_type *rectype){
int32_t field; // сюда поместим значение поля
field = rectype[id].func(rec + rectype[id].offset);
// дальше делаем с этим field то, что нужно
}
typedef int32_t (value*)(void*); // тип описания функции, возвращающей значение поля
typedef struct{
uint8_t offset; // смещение пол относительно начала структуры
value func; // функция, которая вернет значение поля
} rec_type;
int32_t get_byte(char *ptr){
return *ptr;
}
int32_t get_int(int *ptr){
return *ptr;
}
// и так далее для всех вариантов полей, которые могут быть приведены к целочисленному значению
Пт фев 26, 2021 21:25:15
Сб фев 27, 2021 15:18:34
Чт мар 18, 2021 20:59:21
Вс апр 18, 2021 06:26:03
... Тут, очевидно, можно выкрутиться через таблицу обработчиков, принимающих `void *` и уже внутри знающих, что делать со своими полями и какой тип они имеют...