C++ 复制结构的一部分

C++ 复制结构的一部分,c++,c,pointers,C++,C,Pointers,我试图复制一个大型结构的一部分,我希望我可以使用指针算法一次复制它的一部分。所以如果我有以下结构 struct { int field1; char field2; myClass field3; . . . myOtherClass field42; } myStruct; struct origionalStruct; struct *pCopyStruct; 我可以使用memcpy()使用指针算法复制它的一部分吗 memcpy(pCopyStruct, &am

我试图复制一个大型结构的一部分,我希望我可以使用指针算法一次复制它的一部分。所以如果我有以下结构

struct {
  int field1;
  char field2;
  myClass field3;
  .
  .
  .
  myOtherClass field42;
} myStruct;
struct origionalStruct;
struct *pCopyStruct;
我可以使用memcpy()使用指针算法复制它的一部分吗

memcpy(pCopyStruct, &origionalStruct.field1, 
      (char*)&origionalStuct.field1 - (char*)&origionalStuct.field23);

我知道指针算法只对数组有效,但我希望我可以通过将所有内容转换为(char*)来解决这个问题

是的,您可以:

memcpy(pCopyStruct, &origionalStruct.field1, 
  (char*)&origionalStuct.field23 - (char*)&origionalStuct.field1);
但是,您可能希望使用
stddef.h
中的
offsetof()

memcpy(pCopyStruct, &originalStruct.field1, 
  offsetof(struct myStruct, field23)-offsetof(struct myStruct, field1));
其中,如果
field1
位于偏移量0处(结构中的第一个),则可以省略减法

为完整起见,宏的偏移量可以定义为:

#define offsetof(st, m) ((size_t)(&((st *)0)->m))

最好将要复制的字段放入嵌套结构中,并将其分配给新结构的相应字段。这将避免书写,极大地提高可读性,并且(至少不是最后一次)保持类型安全。memcpy没有提供的所有功能

如果复制的字段位于结构的末尾或开头,则offsetof()或使用封闭字段的地址显然不起作用

struct {
    int field1;
    struct { char fields } cpy_fields;
} a, b;

a.cpy_fields = b.cpy_fields;
使用gcc时,您可以启用plan9扩展并使用匿名结构,但内部结构需要typedef:

typedef struct { char field1; } Inner;

struct {
    int field1;
    Inner;
} a, b;
这不会更改可以执行以下操作的现有代码:
a.field2
。您仍然可以通过结构的类型名(前提是外部结构中只有一个实例)作为一个整体访问该结构:
a.Inner=b.Inner

虽然第一部分(匿名结构)自C99以来是标准的,但后一部分是plan9扩展的一部分(它的其他特性也很有趣)。实际上,另一个特性可能会为您的问题提供更好的解决方案。你可能会看一看,让它解决一两秒钟,以得到的影响。仍然奇怪为什么这个特性没有使它成为标准(没有额外的代码,更多类型的安全性,更少的强制转换)。< / P> < P> C++的。 使用memcpy()复制对象的成员变量会破坏封装,通常不是好的做法。也就是说,只有在你有充分理由的情况下才这样做。如果你小心的话,它可以工作,但是你使你的程序变得非常脆弱:你增加了将来的更改引入bug的风险


例如,另请参见

“我知道指针算法仅对数组有效”不正确,它在对象内部有效。它应该是
struct myStruct origionalStruct
结构myStruct*pcopystuct
@LuchianGrigore同一数组外的两个指针的差异是UB,应该尽可能避免。克劳迪斯:你不能将指针投射到
void*
。这可能会隐藏类型错误,如果任何一方预期为
void*
,但实际上并非如此。如果有人告诉你不是这样,就指着他,告诉他读标准。offsetof(又称为_offsetof())是标准的,所以你不应该定义它。此外,强制转换将抑制类型错误检测。您可以使用gcc扩展来维护这一点,但为什么要使用gcc扩展,因为gcc提供C99兼容性(除了少数构造);刚看到C++标签。我将澄清这是否与C或C++有关(或者确实需要对两者都有答案),因为所需的方法对于每个语言来说都必须是非常不同的。就我自己而言,我确实希望这是纯C相关的,因此标记可能会被to删除。