質問

I have the following two structures. I need to copy d, e, f from source to destination using memcpy and offsetof. How can I do this?

struct source
{
    int a;
    int b;
    int c;
    int d;
    int e;
    int f;
};

struct destination
{
    int d;
    int e;
    int f;
};
役に立ちましたか?

解決

Generally, You cannot reliably do it using memcpy, because the compiler is allowed to pad the two structures differently. So the safest way of performing a partial copy would be to assign the three fields individually.

However, since the compiler inserts padding only between members with different alignment requirements, in your specific case you can use memcpy like this:

struct source s {1,2,3,4,5,6};
struct destination d = {100, 200, 300};
memcpy(&d, ((char*)(&s))+offsetof(struct source,d), offsetof(struct source,f)-offsetof(struct source,d)+sizeof(int));

The offset of destination's d is guaranteed to be zero because it is the initial member of the structure. Since members d, e, and f have identical alignment requirements, the padding, if any, will go after them in the struct destination, and before or after them in the struct source.

Cast to char* is required because the offset is expressed in bytes.

The expression

offsetof(struct source,f)-offsetof(struct source,d)+sizeof(int)

is the length of the run between d and f, inclusive. Note that using sizeof(struct destination) is not safe, because it may have padding at the end which is not present in struct source, causing a read past the allocated memory.

他のヒント

As "dasblinkenlight" said, this can't be done reliably by memcpy due to possible padding. You may however do something like this:

struct Part1
{
    int a;
    int b;
    int c;
};

struct Part2
{
    int d;
    int e;
    int f;
};

struct source
{
    struct Part1 p1;
    struct Part2 p2;
};

struct destination
{
    struct Part2 p2;
};

// ...
src.p2 = dst.p2;

For this scenario you can also use int pointer to the source and destination structures and then assign the value in destination pointer and decrease both source and destination int pointer.

The snippet of the code is as follows:-

struct destination * my_copy (struct source *pfSrc, struct destination *pfDes)
{
  int *pSrc = (int *)pfSrc;
  int *pDes = (int *)pfDes;
  pSrc += (sizeof (struct source)/sizeof (int)) - 1;
  pDes += (sizeof (struct destination)/sizeof (int)) - 1;
  do
  {
    *pDes = *pSrc;
    pSrc--;
  }while (pDes-- != (int *)pfDes);
return pfDes;
}
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top