导读 | 最近在做通信协议的解析处理、传递分析等问题,总是遇到通信帧中的结构体拷贝等问题,遇到了一些坑,也是比较基础但是易错的C语言知识,一起来探究一下结构体的深拷贝和浅拷贝。 |
C语言中的浅拷贝是指在拷贝过程中,对于指针型成员变量只拷贝指针本身,而不拷贝指针所指向的目标,它按字节复制的。我们分几种情况举例子来看一下。
代码如下:
//在win10_64位+vs2017 //来源:技术让梦想更伟大 //作者:李肖遥 #include typedef struct { char name[64]; int age; }Member; int main(){ Member stu1 = { "LiMing", 18 }; Member stu2; stu2 = stu1; printf("%s,%d\n", stu2.name, stu2.age); system("pause"); return 0; }
运行如下:
代码如下:
//在win10_64位+vs2017 //来源:技术让梦想更伟大 //作者:李肖遥 #include #include #include typedef struct { char *name; int age; }Member; int main() { Member Member1, Member2; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member2 = Member1;/*拷贝*/ snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; printf("%s, %d\n", Member1.name, Member1.age); if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } system("pause"); return 0; }
运行如下:
从中我们看到,改变Member2的值,Member1的值也改变了,这说明一片空间被两个不同的子对象共享了,改变一个对象的值另外一个也会随之改变。
我们改变Member2写法,申请内存的代码如下:
//在win10_64位+vs2017 //来源:技术让梦想更伟大 //作者:李肖遥 #include #include #include typedef struct { char *name; int age; }Member; int main() { Member Member1; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member Member2; Member2.name = malloc(sizeof(char) * 64); if (NULL == Member2.name) { printf("malloc failed\n"); } memset(Member2.name, 0, 64); //strcpy(Member2.name, "LiMing"); snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; Member1 = Member2; printf("%s, %d\n", Member2.name, Member2.age if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } if (NULL != Member2.name) { free(Member2.name); Member2.name = NULL; } system("pause"); return 0; }
运行如下:
从中我们看到,当数据成员中有指针时,两个类中的两个指针将指向同一个地址,当对象快结束时,会调用两次free函数,此时Member2已经是野指针(图中有X的错误标志),这个野指针指向的内存空间已经被释放掉,再次释放会报异常错误,要解决这个问题就要涉及到深拷贝了。
深拷贝除了拷贝其成员本身的值之外,还拷贝成员指向的动态内存区域内容,深拷贝会在堆内存中另外申请空间来储存数据。
解决的思路是在释放掉被赋值指针变量的旧指向内存时,重新对其开辟新内存,这种情况下两个结构体中指针地址不同,但是指向的内容是一致的。代码如下:
//在win10_64位+vs2017 //来源:技术让梦想更伟大 //作者:李肖遥 #include #include typedef struct { char *name; int age; }Member; int main() { Member Member1; Member1.name = malloc(sizeof(char) * 64); if (NULL == Member1.name) { printf("malloc failed\n"); } memset(Member1.name, 0, 64); //strcpy(Member1.name, "LiMing"); snprintf(Member1.name, 64, "LiMing"); Member1.age = 18; Member Member2; Member2.name = malloc(sizeof(char) * 64); if (NULL == Member2.name) { printf("malloc failed\n"); } memset(Member2.name, 0, 64); //strcpy(Member2.name, "LiMing"); snprintf(Member2.name, 64, "LiXiaoYao"); Member2.age = 29; if (Member1.name != NULL) { free(Member1.name); Member1.name = NULL; } Member1.name = malloc(strlen(Member2.name) + 1); strcpy(Member1.name, Member2.name); printf("%s, %d\n", Member1.name, Member1.age); if (NULL != Member1.name) { free(Member1.name); Member1.name = NULL; } if (NULL != Member2.name) { free(Member2.name); Member2.name = NULL; } system("pause"); return 0; }
运行如下:
使用C语言来说,深拷贝浅拷贝的概念我们不需要深究,在进行结构体拷贝的时候,结构体成员是非指针的话,那么直接赋值是没有任何问题的,建议使用这种方式,避免浅拷贝这类不易发现的错误产生。
如果成员有指针类型,我们就需要重写拷贝函数,自己定义拷贝行为了,这一点我们需要尤为注意。
原文来自:
本文地址://q13zd.cn/deep-and-shallow-c-structure-member.html编辑:J+1,审核员:逄增宝
Linux大全:
Linux系统大全: