将一个结构复制到另一个结构

我知道我可以按成员复制结构成员,但是我可以对结构执行 memcpy操作吗?

这样做明智吗?

在我的结构中,我还有一个字符串作为成员,我必须将它复制到具有相同成员的另一个结构中。我该怎么做?

235728 次浏览

如果结构是兼容的类型,是的,你可以这样做:

memcpy (dest_struct, source_struct, sizeof (*dest_struct));

你唯一需要注意的是,这是一个 肤浅副本。换句话说,如果您有一个指向特定字符串的 char *,那么 都有结构将指向同一个字符串。

改变其中一个字符串字段(char *指向的数据,而不是 char *本身)的内容也会改变另一个字符串字段。

如果您想要一个简单的副本,而不必手动做每个字段,但与非浅字符串副本的额外好处,使用 strdup:

memcpy (dest_struct, source_struct, sizeof (*dest_struct));
dest_struct->strptr = strdup (source_struct->strptr);

这将复制结构的整个内容,然后深度复制字符串,有效地为每个结构提供一个单独的字符串。

而且,如果您的 C 实现没有 strdup(它不是 ISO 标准的一部分) ,那么 从这里拿一个

可以使用 memcpy结构,也可以像分配其他值一样分配它们。

struct {int a, b;} c, d;
c.a = c.b = 10;
d = c;

从 C90开始,你可以简单地使用:

dest_struct = source_struct;

只要字符串存储在数组中:

struct xxx {
char theString[100];
};

否则,如果它是一个指针,就需要手动复制它。

struct xxx {
char* theString;
};


dest_struct = source_struct;
dest_struct.theString = malloc(strlen(source_struct.theString) + 1);
strcpy(dest_struct.theString, source_struct.theString);

通过简单分配进行复制是最好的,因为它更短,更容易阅读,并且具有更高的抽象级别。不需要(对代码的人类读者)说“把这些位从这里复制到那里”,并要求读者考虑复制的大小参数,你只需要做一个简单的赋值(“把这个值从这里复制到这里”)。对于尺寸是否正确,我们毫不犹豫。

此外,如果结构是大量填充,赋值可能使编译器发出一些更有效的东西,因为它不必复制填充(并且它知道它在哪里) ,但 mempcy()不这样做,所以它总是复制你告诉它复制的确切字节数。

如果你的字符串是一个实际的数组,例如:

struct {
char string[32];
size_t len;
} a, b;


strcpy(a.string, "hello");
a.len = strlen(a.string);

那么您仍然可以使用普通赋值:

b = a;

为了得到一份完整的副本。但是,对于这样建模的可变长度数据,这不是最有效的复制方法,因为整个数组将始终被复制。

不过要注意,复制包含指向堆分配内存的指针的结构可能有点危险,因为这样做的话,您就是指针 伪装,并且通常会使复制操作之后指针的所有者变得模糊不清。

对于这些情况,“深度拷贝”实际上是唯一的选择,这需要放在函数中。

  1. 可以使用 struct 将写入内容读入文件。 你不需要把它铸造成一个字符 * 。 结构大小也将保留。 (这一点与主题并不相近,但你可以猜一猜: 在硬盘存储器上的行为通常与 RAM 1相似

  2. 要移动(从)单个字符串字段,必须使用 strncpy 以及暂态字符串缓冲区 '\0'终止。 您必须记住记录字符串字段的长度

  3. 要移动其他字段,可以使用点符号,例如: NodeB->one=intvar; floatvar2=(NodeA->insidebisnode_subvar).myfl;

    struct mynode {
    int one;
    int two;
    char txt3[3];
    struct{char txt2[6];}txt2fi;
    struct insidenode{
    char txt[8];
    long int myl;
    void * mypointer;
    size_t myst;
    long long myll;
    } insidenode_subvar;
    struct insidebisnode{
    float myfl;
    } insidebisnode_subvar;
    } mynode_subvar;
    
    
    typedef struct mynode* Node;
    
    
    ...(main)
    Node NodeA=malloc...
    Node NodeB=malloc...
    
  4. You can embed each string into a structs that fit it, to evade point-2 and behave like Cobol: NodeB->txt2fi=NodeA->txt2fi ...but you will still need of a transient string plus one strncpy as mentioned at point-2 for scanf, printf otherwise an operator longer input (shorter), would have not be truncated (by spaces padded).

  5. (NodeB->insidenode_subvar).mypointer=(NodeA->insidenode_subvar).mypointer will create a pointer alias.
  6. NodeB.txt3=NodeA.txt3 causes the compiler to reject: error: incompatible types when assigning to type ‘char[3]’ from type ‘char *’
  7. point-4 works only because NodeB->txt2fi & NodeA->txt2fi belong to the same typedef !!

    A correct and simple answer to this topic I found at In C, why can't I assign a string to a char array after it's declared? "Arrays (also of chars) are second-class citizens in C"!!!

你可以使用以下方法来实现你的目标:

struct student
{
char name[20];
char country[20];
};
void main()
{
struct student S={"Wolverine","America"};
struct student X;
X=S;
printf("%s%s",X.name,X.country);
}

在 C 中,memcpy 只是愚蠢地冒险。只要所有三个参数都正确,没有一个结构成员是指针(或者,您显式地打算做一个浅拷贝) ,而且 memcpy 不会在结构中浪费时间循环(或者性能从来都不重要) ,那么毫无疑问,memcpy。除了难以阅读、易受未来更改影响并且必须在代码审查中手工验证(因为编译器不能)的代码之外,您什么也得不到,但是,嘿,是的,当然,为什么不呢。

在 C + + 中,我们进入了荒唐的冒险阶段。您可能拥有不能安全地记忆的类型成员,例如 std: : string,它将导致您的接收结构成为一个危险的武器,无论何时使用都会随机损坏内存。在模拟切片副本时,可能会遇到涉及虚函数的意外情况。优化器可以为您做很多事情,因为它在编译 = 时保证具有完整的类型知识,但是它不能为 memcpy 调用做任何事情。

在 C + + 中有一个经验法则——如果你看到 memcpy 或 memset,就说明有问题。在极少数情况下,这种情况并不正确,但是它们并不涉及结构。当且仅当有理由 盲目的复制 字节时,才使用 memcpy。

另一方面,赋值很容易阅读,在编译时检查正确性,然后在运行时智能地移动 价值观。没有坏处。