复制C中包含字符指针的两个结构

复制C中包含字符指针的两个结构,c,pointers,struct,C,Pointers,Struct,复制两个包含字符数组的结构的标准方法是什么 下面是一些代码: #include stdio.h> #include string.h> #include stdlib.h> typedef struct { char* name; char* surname; } person; int main(void){ person p1; person p2; p1.name = (char*)malloc(5); p1.

复制两个包含字符数组的结构的标准方法是什么

下面是一些代码:

#include stdio.h>
#include string.h>
#include stdlib.h>

typedef struct {
    char* name;
    char* surname;
} person;

int main(void){
    person p1;
    person p2;

    p1.name     = (char*)malloc(5);
    p1.surname  = (char*)malloc(5);

    strcpy(p1.name, "AAAA");
    strcpy(p1.surname, "BBBB");

    memcpy(&p2, &p1, sizeof(person));
    free(p1.name);
    printf("%s\n", p2.name);
    return 0;
}
printf(“%s\n”,p2.name)不打印某些内容,因为我释放了缓冲区

我的结构的问题是它们比struct
person
大。它们包含数百个字符指针,我必须逐个复制每个成员


是否有另一种方法可以复制包含字符数组的两个结构,而不必为每个成员使用
malloc
strcpy

您别无选择,只能自己提供一个复制函数:

void copy_person(person *dst, const person *src)
{
    dst->name = malloc(strlen(src->name) + 1);
    dst->surname = malloc(strlen(src->surname) + 1);
    strcpy(dst->name, src->name);
    strcpy(dst->surname, src->surname);
}
其中可能更为详细:检查错误,在辅助函数中分解
strlen+strcpy
,等等


C++中的复制构造函数是这样的.

< P>是的,包含char <强>数组的复制结构将不会有任何问题,但是结构有char <强>指针< /强>(或任何类型的指针),您将不得不手动进行。


还请注意,C中不需要malloc的返回类型转换(它在C++中),并且可以隐藏malloc缺少的原型。

如果要进行复制,必须为任何指针分配内存。但是,您始终可以将指针指向已分配的内存。例如,您可以执行以下操作:

p2.name = p1.name (p1.name is already allocated memory)
这是危险的,因为对同一内存位置有多个引用。如果释放
p1.name
p2.name
,将导致危险情况

为了复制整个内容,必须将内存分配给结构p2的指针

p2.name = <allocate memory>
Copy individual struct members instead of a memcpy of the entire struct
p2.name=
复制单个结构成员,而不是整个结构的memcpy
这是因为内存不是以连续的方式分配的。另外,
sizeof(struct)
将给出结构成员的大小,而不是分配给它的内存

例如
sizeof(p2)=8=sizeof(p1)=sizeof(person)
即使在将内存分配给
p1
的成员之后


如果成员是字符数组,情况就不同了。

有点开箱思考:

由于结构的结构是静态的,因此可以编写一个小的实用程序或脚本来生成复制代码

将结构定义的源代码作为输入,然后设计一组规则来生成复制代码


这是一个快速的问题,我不知道手动编写复制代码是否会更快,但至少这是一个更有趣的问题。

要详细说明Alexandre C的答案,您可能需要将
malloc()
作为一个单独的操作,这样
free()
也很简单

这种方法提供了一定程度的保护,因为单个
malloc()
要么成功,要么失败,这样您就不会在构建副本的过程中遇到
malloc()
失败的问题。使用这种方法,您可以将
person
与指向
person
的指针混合在一起,这些指针已被malloced,因此您可能希望有两种不同的数据类型,如下所示,以便更好地标记哪个是哪个

我提供了两种复制方法,一种是使用C标准库函数
strcpy()
strlen()
,另一种是使用一个简单函数进行直接复制,并返回指向目标缓冲区中停止位置的指针

我没有尝试编译这个例子,所以可能有问题

这种方法可能存在一个问题。由于单个字符串不是malloced,如果您使用指针移动单个字符串,并且认为每个字符串都是其自己的malloced内存区域,则可能会遇到问题。这种方法假定需要整个对象,或者不需要任何对象

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>

    typedef struct {
        char* name;
        char* surname;
        char* address1;
    } person, *personptr;

    // copy a string to destination string return pointer after end of destination string
    char * StrCpyRetEnd (char *pDest, char *pSrc)
    {
        while (*pDest++ = *pSrc++);
        return pDest;
    }
    personptr DeepCopyPerson (person *pSrc)
    {
        personptr     pDest = 0;
        unsigned int  iTotalSize = sizeof(person);

        iTotalSize += (strlen(pSrc->name) + 1) * sizeof(char);
        iTotalSize += (strlen(pSrc->surname) + 1) * sizeof(char);
        iTotalSize += (strlen(pSrc->address1) + 1) * sizeof(char);
        pDest = malloc(iTotalSize);
        if (pDest) {
#if 1
            // alternative one without a helper function
            pDest->name = (char *)(pDest + 1);  strcpy (pDest->name, pSrc->name);
            pDest->surname = pDest->name + strlen(pDest->name) + 1; strcpy (pDest->surname, pSrc->surname);
            pDest->address1 = pDest->surname + strlen(pDest->surname) + 1; strcpy (pDest->address1, pSrc->address1);
#else
            // alternative two using StrCpyRetEnd () function
            pDest->name = (char *)(pDest + 1);
            pDest->surname = StrCpyRetEnd (pDest->name, pSrc->name);
            pDest->address1 = StrCpyRetEnd (pDest->surname, pSrc->surname);
            strcpy (pDest->address1, pSrc->address1);
#endif
        }
        return pDest;
    }

    int main(void){
        person    p1;  // programmer managed person with separate mallocs
        personptr p2;  // created using ClonePerson()

        p1.name     = malloc(5);
        p1.surname  = malloc(5);
        p1.address1 = malloc(10);

        strcpy(p1.name,"AAAA");
        strcpy(p1.surname,"BBBB");
        strcpy(p1.address1,"address1");

        p2 = DeepCopyPerson (&p1);

        free(p1.name);
        printf("%s\n", p2->name);

        free (p2);   // frees p2 and all of the memory used by p2
        return 0;
    }
#包括
#包括
#包括
类型定义结构{
字符*名称;
查*姓;
字符*地址1;
}个人,*personptr;
//将字符串复制到目标字符串结束后的目标字符串返回指针
char*StrCpyRetEnd(char*pDest,char*pSrc)
{
而(*pDest++=*pSrc++);
返回pDest;
}
personptr DeepCopyPerson(person*pSrc)
{
personptr pDest=0;
无符号整数iTotalSize=sizeof(人);
iTotalSize+=(strlen(pSrc->name)+1)*sizeof(char);
iTotalSize+=(strlen(pSrc->姓氏)+1)*sizeof(char);
iTotalSize+=(strlen(pSrc->address1)+1)*sizeof(char);
pDest=malloc(iTotalSize);
如果(pDest){
#如果1
//没有辅助函数的备选方案
pDest->name=(char*)(pDest+1);strcpy(pDest->name,pSrc->name);
pDest->姓氏=pDest->姓名+strlen(pDest->姓名)+1;strcpy(pDest->姓氏,pSrc->姓氏);
pDest->address1=pDest->姓氏+strlen(pDest->姓氏)+1;strcpy(pDest->address1,pSrc->address1);
#否则
//使用StrCpyRetEnd()函数的备选方案二
pDest->name=(字符*)(pDest+1);
pDest->姓氏=StrCpyRetEnd(pDest->name,pSrc->name);
pDest->address1=strcpyritend(pDest->姓氏,pSrc->姓氏);
strcpy(pDest->address1,pSrc->address1);
#恩迪夫
}
返回pDest;
}
内部主(空){
人员p1;//程序员管理的人员,具有单独的malloc
personptr p2;//使用ClonePerson()创建
p1.name=malloc(5);
p1.姓氏=马洛克(5);
p1.address1=malloc(10);
strcpy(p1.名称,“AAAA”);
strcpy(p1.姓“BBBB”);
strcpy(p1.地址1,“地址1”);
p2=深度复制人(&p1);
免费(p1.姓名);
printf(“%s\n”,p2->name);
释放(p2);//释放p2和所使用的所有内存