Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Как переписать данные из массива в структуру?
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Программирование
011119xx
Прошу помощи у специалистов в следующем. Часть кода выглядит так:
Код
typedef struct _SETTINGS_DATA
{
     uint8_t                    theme;
     uint8_t                    volume;
     uint16_t                  timing;
} settings_data_t;

typedef settings_data_t *psettings_data_t;

settings_data_t Settings_Data;
uint8_t sFLASH_SPI_Buffer_Rx[512];

void read_settings(void)
{
      ... здесь в буфер sFLASH_SPI_Buffer_Rx читаются данные (уже все работает)...

      ... ЗДЕСЬ НАДО ПЕРЕПИСАТЬ ДАННЫЕ ИЗ sFLASH_SPI_Buffer_Rx В Settings_Data ...

}

void main(void)
{
     ... лишнее опущено ...

     read_settings();

     ... лишнее опущено ...
}


Как это сделать правильно и компактно?
Dog Pawlowa
Цитата(011119xx @ Jul 22 2011, 10:13) *
Как это сделать правильно и компактно?


В общем случае никак, поскольку нет никакой информации, как расположены данные в буфере приема.
Это, наверное, и заставляет задавать вопросы. Расскажите, как там байтики приняты, сразу же три строчки сами и нарисуются.

MrYuran
memcpy(sFLASH_SPI_Buffer_Rx, &Settings_Data, sizeof(Settings_Data));
Предварительно обратно - в обратном порядке.
Тогда будет совершенно по барабану размерность, выравнивание и эндианность.
011119xx
Цитата(Dog Pawlowa @ Jul 22 2011, 13:28) *
... поскольку нет никакой информации, как расположены данные в буфере приема.

Если описать грубо то так:
sFLASH_SPI_Buffer_Rx[0] соответствует theme,
sFLASH_SPI_Buffer_Rx[1] соответствует volume,
sFLASH_SPI_Buffer_Rx[2] соответствует мл. байт timing,
sFLASH_SPI_Buffer_Rx[3] соответствует ст. байт timing.
Danis
Цитата(011119xx @ Jul 22 2011, 10:13) *
Как это сделать правильно и компактно?


Начнем с того, что за это массив и как он получен?
Если я Вас правильно понял, Вам нужно заполнить экземпляр структуры данными, хранящимися в массиве. Для этого изначально нужно этот массив получить, вычитав экземпляр. Размер массива должен быть как минимум sizeof(settings_data_t) в Вашем случае. Помните, что размер структуры не обязательно равен сумме типов данных в ней описанных.
Так, копирование экземпляра структуры в массив и наоборот будет выглядеть так:
Код
typedef struct _SETTINGS_DATA
{
     unsigned char    theme;
     unsigned char    volume;
     unsigned short    timing;
} settings_data_t;

settings_data_t Settings_Data;

unsigned char Data[4];  // Размер в байтах равен(кратен)  sizeof(Settings_Data)

void f(void)
{
    Settings_Data.theme  = 8;
    Settings_Data.timing = 478;
    Settings_Data.volume = 45;

    memcpy( &Data[0], &Settings_Data,  sizeof(Settings_Data) );  // Из структуры в массив
    memcpy( &Settings_Data, &Data[0], sizeof(Settings_Data) );  // Из массива в структуру

}
011119xx
Цитата(MrYuran @ Jul 22 2011, 13:38) *
memcpy(sFLASH_SPI_Buffer_Rx, &Settings_Data, sizeof(Settings_Data));
Предварительно обратно - в обратном порядке.
Тогда будет совершенно по барабану размерность, выравнивание и эндианность.

Спасибо. Работает превосходно.
Danis
Цитата(011119xx @ Jul 22 2011, 10:42) *
Если описать грубо то так:
sFLASH_SPI_Buffer_Rx[0] соответствует theme,
sFLASH_SPI_Buffer_Rx[1] соответствует volume,
sFLASH_SPI_Buffer_Rx[2] соответствует мл. байт timing,
sFLASH_SPI_Buffer_Rx[3] соответствует ст. байт timing.


так не надо!
Dog Pawlowa
Цитата(MrYuran @ Jul 22 2011, 10:38) *
Тогда будет совершенно по барабану размерность, выравнивание и эндианность.

Это если отправитель пользуется структурой того же типа, что не факт.
Иначе бы автор эту структуру отправлял, и скорее всего и принять бы смог.
aaarrr
Цитата(Danis @ Jul 22 2011, 11:54) *
unsigned char Data[4]; // Размер в байтах равен(кратен) sizeof(Settings_Data)

Тогда почему бы так и не написать прямо в коде вместо комментария? А то потом settings_data_t десять раз поменяется, а четверка будет благополучно забыта.
sergeeff
Цитата(aaarrr @ Jul 22 2011, 13:16) *
Тогда почему бы так и не написать прямо в коде вместо комментария? А то потом settings_data_t десять раз поменяется, а четверка будет благополучно забыта.


Ну и объявить по простому:

Код
typedef struct _SETTINGS_DATA
{
     unsigned char    theme;
     unsigned char    volume;
     unsigned short    timing;
} settings_data_t;

unsigned char Data[sizeof(settings_data_t)];


И memcpy совсем не нужно:

Код
settings_data_t abc = *(settings_data_t *)Data;


Компилятор сам все скопирует.
Danis
Цитата(aaarrr @ Jul 22 2011, 13:16) *
а четверка будет благополучно забыта.


Согласен с Вами, просто «разжевал» для ТС, чтоб синтаксисом не перегружать, сам бы вообще через new массив создал.


Цитата(sergeeff @ Jul 22 2011, 13:38) *
Код
settings_data_t abc = *(settings_data_t *)Data;

Компилятор сам все скопирует.


ИМХО тут комментировать надо, что за звездочки и для чего, запутаете ТС. Раз такой вопрос поднялся, тут для ТС пояснять нужно, что есть приведение типов а, что разименование.
MrYuran
Цитата(Danis @ Jul 22 2011, 13:50) *
Согласен с Вами, просто «разжевал» для ТС, чтоб синтаксисом не перегружать, сам бы вообще через new массив создал.

Вот уж чего точно не следует делать, так это new() без всяких на то причин.
Тем более что в си есть только аллоки. Любой локальный массив создаётся на стеке, а потом гарантированно уничтожается, причём без накладных расходов.
К тому же непонятно, зачем вообще плодить эти массивы.
Почему нельзя воспользоваться исходным буфером.
Danis
Конечно, можно вообще обойтись без массивов, определил адрес структуры, ее размер и гоняй туда/суда сколько влезет.
Hellper
есть подводный камень связанный с little-endian и big-endian требующий внимания
sergeeff
Цитата(Hellper @ Jul 22 2011, 14:51) *
есть подводный камень связанный с little-endian и big-endian требующий внимания


По большому счету тут куча подводных камней. В том числе как упакована структура и упакована ли? Да и вся постановка вопроса мутная.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.