Reputation: 3
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:
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
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