c语言如何实现结构体的深度复制

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c语言如何实现结构体的深度复制相关的知识,希望对你有一定的参考价值。

求助大神

  使用memcpy即可, 比如你另外建立一个结构体sortbook[1000]用来保存排序结果,将book中的第i个元素赋值到sortbook的第j个元素中
memcpy(&sortbook[j], &book[i], sizeof(struct book));
用这个函数需要#include <string.h>

  函数原型
  void *memcpy(void*dest, const void *src, size_t n);
  功能
  由src指向地址为起始地址的连续n个字节的数据复制到以destin指向地址为起始地址的空间内。
  头文件
  #include<string.h>
  返回值
  函数返回一个指向dest的指针。
  说明
  1.source和destin所指内存区域不能重叠,函数返回指向destin的指针。
  2.与strcpy相比,memcpy并不是遇到'\0'就结束,而是一定会拷贝完n个字节。

  memcpy用来做内存拷贝,你可以拿它拷贝任何数据类型的对象,可以指定拷贝的数据长度;
  例:
  char a[100], b[50];
  memcpy(b, a,sizeof(b)); //注意如用sizeof(a),会造成b的内存地址溢出。
  strcpy就只能拷贝字符串了,它遇到'\0'就结束拷贝;例:
  char a[100], b[50];
  strcpy(a,b);
  3.如果目标数组destin本身已有数据,执行memcpy()后,将覆盖原有数据(最多覆盖n)。如果要追加数据,则每次执行memcpy后,要将目标数组地址增加到你要追加数据的地址。
  //注意,source和destin都不一定是数组,任意的可读写的空间均可。
参考技术A

结构体,不像C++中的类,可以通过修改拷贝构造函数来实现深拷贝。


结构的的深拷贝,只能写一个单独的函数来实现了。


下面的是一个例子:

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

struct Student
char * firstName;
int num;
;

void CreateStudent(Student * tar)
tar->firstName = new char[10];

void DeleteStudent(Student * tar)
delete tar->firstName;

void DeepCopyStudent(const Student * src, Student* tar)
strcpy(tar->firstName, src->firstName);
tar->num = src->num;

void PrintStudent(const Student * tar)
printf("%s\\n", tar->firstName);


int main()
Student *s1, *s2;
s1 = new Student();
s2 = new Student();
CreateStudent(s1);
char *name = "Hello";
strcpy(s1->firstName, name);
CreateStudent(s2);
DeepCopyStudent(s1, s2);
PrintStudent(s1);
DeleteStudent(s1);
delete s1;
PrintStudent(s2); //在删除s1之后,s2仍然可以正常输出,说明深拷贝
DeleteStudent(s2);
delete s2;


return 0;

参考技术B //如有
struct A   int i;  char *pc;;
//并定义
struct A st =  0, "a const string ptr" ;
//则可以用
struct A *p = (struct A *) malloc(sizeof(struct A));*p = st;
//完成复制。用
free(p);
 p = NULL;
//完成释放。

追问

这不是浅度复制吗

追答//如有
struct A   int i;  char *pc;;
//并定义
struct A *st;
.........
//则可以用
struct A *p = (struct A *) malloc(sizeof(struct A));
memcpy(p,st,sizeof(st))
//完成复制。用
free(p);
 p = NULL;
//完成释放。

使用memcpy呢,像上面这样

参考技术C 这个关键看结构体的数据域,只要对其中的指针类型处理即可,拷贝其内容而非其本身,这样才释放指针是才不会重复释放同一内存区域追问

大神能不能用代码举个例子

追答

最简单的例子便是C的string的实现

struct CString

char * ptr;
int size;
;

void shallowCopy(struct CString * dst, struct CString * src)

dst->size = src->size;
dst->ptr = src->ptr;


void depthCopy(struct CString * dst, struct CString * src)

if(dst->size != src->size)

dst->size = src->size;
free(dst->ptr);
dst->ptr = NULL;
dst->ptr = (char *)calloc(dst->size + 1, sizeof(char));

strcpy(dst->ptr, src->ptr);

参考技术D 弱弱的问:啥是深度复制?追问

递归复制。好像所谓不用指针。我也不清楚。

递归复制。好像所谓不用指针。我也不清楚。

在 C/C++ 中使用 ProtoBuf 进行深度复制

【中文标题】在 C/C++ 中使用 ProtoBuf 进行深度复制【英文标题】:Deep-copying with ProtoBuf in C/C++ 【发布时间】:2015-04-27 21:37:51 【问题描述】:

假设我有一个指针数组,每个指针都指向结构体,这些结构体中可能又包含指向其他结构体的指针;是否可以使用 protobuf 处理序列化?如果有,怎么做?

任何帮助将不胜感激。

【问题讨论】:

"How" 是什么意思,你想解释一下,如何在 c++ 中使用 protobuf? @AlanStokes:我实际上正在为不同的项目使用两者。任何一个方面的帮助都会很棒。 @MikeMB:我希望有一个嵌套指针可能发挥作用的例子。我能找到的例子都相当琐碎。 【参考方案1】:

您考虑这个问题的方式与考虑 protobuf 时需要考虑的方式相反。 Protobufs 不采用现有的数据结构并将它们序列化。它们采用序列化协议并为您创建填充的数据结构。

话虽如此,嵌套序列化非常简单:

// nested.proto
message Inner 
    required string value = 1;


message Outer 
    required Inner inner = 1;


message Pointers 
    repeated Outer outer = 1;

假设你已经正确编译了这个,你可以使用这个协议从外向内工作。也就是说,你从最高的结构 Pointers 开始,然后进入 Inner 对象:

Pointers pointers;
for (int i = 0; i < 10; ++i) 
    auto outer = pointers.add_outer();
    auto inner = outer->mutable_inner();
    inner->set_value(std::to_string(i));


std::stringstream stream;
pointers.SerializeToOstream(&stream);

...

Pointers parsed_pointers;
parsed_pointers.ParseFromIstream(&stream);
for (int i = 0; i < parsed_pointers.outer_size(); ++i) 
    std::cout << parsed_pointers.outer(i).inner().value() << std::endl;


// This prints 0, 1, 2, ..., 9 all on their own lines

可以从Inner 消息开始,但是将所有权传递给Outer 消息的方式并不简单或明显:

Inner* inner = new Inner();
inner->set_value("Hello world");
Outer outer;
outer.set_allocated_inner(inner);

调用该方法将捕获inner 指针的所有权,因此您不应该自己手动delete

【讨论】:

【参考方案2】:

我认为还有另一种方法也很有帮助。因为.set_allocated_*(A) 有一个副作用会破坏A。要仅从A 复制,您可以尝试.mutable_*()-&gt;CopyFrom(A)

【讨论】:

以上是关于c语言如何实现结构体的深度复制的主要内容,如果未能解决你的问题,请参考以下文章

深度剖析结构体@自定义类型1---结构体的声明,自引用,变量定义和初始化 + 结构体内存对齐 + 结构体传参 + 结构体实现位段

用c或c++实现结构体的序列化和反序列化

结构体怎么定义

在 C/C++ 中使用 ProtoBuf 进行深度复制

C语言怎么将结构体的内容复制到另一个结构体中

C语言中如何将16位结构体定义为4位和12位两部分