C: копирование элементов структуры из одной структуры в другую похожую, но разную структуру - PullRequest
0 голосов
/ 28 апреля 2020

У меня есть следующие две структуры:

typedef struct
{
    double num1;
    double num2;
    //double num3, num4, num5, num6;  // Removed unused variables to reduce data size
    double num7;
    double num8;
} InternalData;

typedef struct
{
    double num1;
    double num2;
    char   filler[32];  // Used to be num3 - num6
    double num7;
    double num8;
} ExternalData;

Скажем, у меня есть следующие две переменные, я ищу эффективный способ скопировать внутреннюю структуру во внешнюю структуру, пропуская "заполнитель" Данные во внешнем. Эта копия происходит на большом количестве данных много раз в секунду.

InternalData internal = { 1.0, 2.2, 12.3, 494.7 };
ExternalData external;

Очевидно, я могу сделать что-то подобное, чтобы скопировать внутренние элементы на внешние. Но я не уверен, насколько это эффективно с большим объемом данных и как часто копируются вещи.

external.num1 = internal.num1;
external.num2 = internal.num2;
external.num7 = internal.num7;
external.num8 = internal.num8

В структуре InternalData были удалены номера от num3 до num6, чтобы уменьшить размер внутренних данных; тем не менее, размер байта ExternalData не может измениться, таким образом, массив char заполнителя.

Когда структуры совпали, я смог создать memcpy от одной к другой, потому что они были одной и той же структурой. Теперь, когда они не совпадают, что было бы наиболее оптимальным решением для копирования данных из внутреннего в внешний?

Я получил кое-что работающее, выполнив memcpy от начала до заполнителя, а затем от заполнителя до конца. Что-то вроде этого:

int internaloffset = 0;
int externaloffset = 0;
memcpy((char*)&external + externaloffset, (char*)&internal + internaloffset, sizeof(double)*2);
internaloffset += sizeof(double)*2;
externaloffset += sizeof(double)*2 + sizeof(char)*32;
memcpy((char*)&external + externaloffset, (char*)&internal + internaloffset, sizeof(double)*2);

В моем реальном коде у меня есть смещения для вычисления байтов от начала до заполнителя, поэтому мне не нужно делать sizeof (double) * 2. Копия определенно работает, но я должен быть очень осторожен со своими структурами. Если мои заполнители меняются, и я не обновляю эту копию - она ​​больше не будет копироваться правильно.

Пара замечаний:

  1. Код весь в C.
  2. Внутренние и внешние переменные уже созданы.
  3. Я не могу переместить данные, мне нужно скопировать, поскольку внутреннее используется после копирования.
  4. Не нужно беспокоиться о глубоком копировании указателей в данных, все это тривиальные типы данных.

Кто-нибудь может придумать более элегантное решение для этого? Мне не нравится ни одно из предложенных мной решений, прямое назначение или несколько memcpys. Кроме того, было бы лучшее решение, если бы я мог перенести эту часть кода на C ++?

Любая помощь приветствуется, спасибо!

1 Ответ

0 голосов
/ 28 апреля 2020

Используйте offsetof() для расчета смещений. Добавление и умножение sizeof() не допускает заполнения между элементами.

memcpy(&external, &internal, offsetof(ExternalData, filler));
memcpy(&external.num7, &internal.num7, sizeof(external) - offsetof(ExternalData, num7));
...