Для уточнения ответа Александра С. вы можете выполнить malloc()
как одну операцию, чтобы free()
также был простым.
Этот подход обеспечивает определенную степень защиты в этомсингл malloc()
будет либо успешным, либо неудачным, чтобы у вас не было проблемы с malloc()
неудачей на полпути при создании копии.При таком подходе вы бы смешали person
с указателями на person
, которые были неправильно размещены, поэтому вы можете захотеть иметь два разных типа данных в соответствии с приведенным ниже описанием, чтобы лучше пометить, какой именно.* Я предоставил две альтернативы для копирования, одна из которых использует стандартные библиотечные функции C strcpy()
и strlen()
, а другая - простую функцию, которая выполняет прямое копирование и возвращает указатель на то место, где она остановилась в буфере назначения.1013 *
Я не пытался скомпилировать этот пример, поэтому могут возникнуть проблемы с ним.
Существует один возможный недостаток этого подхода.Поскольку отдельные строки не имеют неправильного расположения, вы можете столкнуться с проблемой, если перемещаете отдельные строки, используя их указатели, с мыслью, что каждая из отдельных строк - это собственная выделенная область памяти.Этот подход предполагает, что весь объект находится в розыске или ни один из них не нужен.
#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;
}