私は次の2つの構造を持っています。とを使用d, e, f
してコピーする必要があります。これどうやってするの?source
destination
memcpy
offsetof
struct source
{
int a;
int b;
int c;
int d;
int e;
int f;
};
struct destination
{
int d;
int e;
int f;
};
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
、構造体の初期メンバーであるため、ゼロであることが保証されています。メンバーd
、e
、およびf
の配置要件は同じであるため、パディングがある場合は、 ではそれらの後に、struct destination
ではそれらの前後に配置されstruct source
ます。
char*
オフセットはバイト単位で表されるため、キャスト先が必要です。
表現
offsetof(struct source,f)-offsetof(struct source,d)+sizeof(int)
d
との間の実行の長さf
(両端を含む) です。sizeof(struct destination)
に存在しない末尾にパディングがありstruct source
、割り当てられたメモリを超えて読み取りが発生する可能性があるため、使用は安全ではないことに注意してください。
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;
このシナリオでは、ソース構造と宛先構造への 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;
}