1

私は次の2つの構造を持っています。とを使用d, e, fしてコピーする必要があります。これどうやってするの?sourcedestinationmemcpyoffsetof

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

struct destination
{
    int d;
    int e;
    int f;
};
4

3 に答える 3

5

memcpy一般に、コンパイラは2 つの構造体を異なる方法でパディングすることが許可されているため、を使用して確実に行うことはできません。したがって、部分コピーを実行する最も安全な方法は、3 つのフィールドを個別に割り当てることです。

ただし、コンパイラは異なるアライメント要件を持つメンバー間にのみパディングを挿入するため、特定のケースでは次のmemcpyように使用できます。

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

destinationのオフセットはd、構造体の初期メンバーであるため、ゼロであることが保証されています。メンバーde、およびfの配置要件は同じであるため、パディングがある場合は、 ではそれらの後に、struct destinationではそれらの前後に配置されstruct sourceます。

char*オフセットはバイト単位で表されるため、キャスト先が必要です。

表現

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

dとの間の実行の長さf(両端を含む) です。sizeof(struct destination)に存在しない末尾にパディングがありstruct source、割り当てられたメモリを超えて読み取りが発生する可能性があるため、使用は安全ではないことに注意してください。

于 2012-05-10T12:47:14.103 に答える
1

memcpy「dasblinkenlight」が言ったように、パディングの可能性があるため、これを確実に行うことはできません。ただし、次のようなことを行うこともできます。

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;
于 2012-05-10T12:54:11.827 に答える
0

このシナリオでは、ソース構造と宛先構造への int ポインターを使用してから、宛先ポインターに値を割り当て、ソースと宛先の両方の int ポインターを減らすこともできます。

コードのスニペットは次のとおりです。

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;
}
于 2012-05-10T13:52:51.483 に答える