t0mf
t0mf

Reputation: 3

C: Copying structure members from one structure to another similar, but different, structure

I have the following two structures:

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;

Say I have the following two variables, I'm looking for an efficient way to copy the internal struct to the external struct, skipping over the "filler" data in the external. This copy is occurring on a large amount of data at many times per second.

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

Obviously I can do something this to copy internal members to external. But I'm not sure how efficient this is with a large amount of data and how often things are copied.

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

In the InternalData structure, num3 through num6 were removed to make the internal data size smaller; however, the ExternalData byte size cannot change, thus the filler char array.

When the structures matched I was able to do a memcpy from one to the other, because they were the same structure. Now that they don't match, what would be the most optimal solution for copying data from internal to external?

I got something working by doing a memcpy from the start to the filler and then from filler to end. Something along the lines of this:

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);

In my actual code I have offset's to calculate bytes from start to filler so I don't have to do sizeof(double)*2. The copy definitely works, but I have to be super careful with my structs. If my fillers change and I don't update this copy - it won't copy correctly anymore.

A couple notes:

  1. The code is all in C.
  2. The internal and external variables are already created.
  3. I can't move data, I need to copy as the internal is used after the copy.
  4. Don't need to worry about deep copy of pointers in the data, everything is trivial data types.

Can anyone think of a more elegant solution to this? I don't like either of the solutions I came up with, direct assignment or multiple memcpys. Also, would there be a better solution if I could migrate this portion of code to C++?

Any help is appreciated, thanks!

Upvotes: 0

Views: 561

Answers (1)

Barmar
Barmar

Reputation: 782755

Use offsetof() to calculate offsets. Adding and multiplying sizeof() doesn't allow for padding between members.

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

Upvotes: 1

Related Questions