复制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)代码>不打印某些内容,因为我释放了缓冲区
我的结构的问题是它们比structperson
大。它们包含数百个字符指针,我必须逐个复制每个成员
是否有另一种方法可以复制包含字符数组的两个结构,而不必为每个成员使用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和所使用的所有内存