018-结构体再进阶及深浅拷贝
1、结构体嵌套一级、二级指针知识点:1.对于创建内存空间的指针,不能向他指向的内存空间写值。
2.malloc申请的空间在结束时需要手工释放,malloc怎么申请的 就要怎么释放;即只能拿到malloc返回的地址才能去释放。
3. malloc申请的内存空间只能够被释放一次,不允许多次释放
熟悉下面这个模型(内存的申请、建立和释放方法):
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
// 结构体套一级、二级指针
struct Teacher
{
char name;
char *a_name;
int age;
char **stuname;
};
//打印
void printfArray(struct Teacher *pArray, int count)
{
int i = 0, j = 0;
for (i = 0; i < count; i++)
{
printf("\n%d", pArray.age);
printf("%s", pArray.name);
printf("%s", pArray.a_name);
for (j = 0; j < 3; j++)
{
printf("%s", pArray.stuname);
}
}
}
//排序
void sortArray(struct Teacher *pArray, int count)
{
int i = 0, j = 0;
struct Teacher tmp;
for (i = 0; i < count; i++)
{
for (j = i + 1; j < count; j++)
{
if (pArray.age < pArray.age)
{
tmp = pArray;
pArray = pArray;
pArray = tmp;
}
}
}
}
// 手工创建结构体数组
struct Teacher * createTArray1(int count)
{
int i = 0, j = 0;
struct Teacher*p1 = (struct Teacher *)malloc(count * sizeof(struct Teacher));
if (p1 == NULL)
{
return NULL;
}
for (i = 0; i < count; i++)
{
memset(&p1, 0, sizeof(struct Teacher));// 给申请的内存空间,每个字节赋0
memset(p1+i, '0', sizeof(struct Teacher)); // 和上面等价
p1.a_name = (char*)malloc(128 * sizeof(char));// 开辟空间给a_name
memset(p1.a_name, 0, 128 * sizeof(char)); //为自己开辟的空间赋初值
//给stuname 手工打造一个二维内存空间
{
char **p2 = (char**)malloc(3 * sizeof(char*));
for (j = 0; j < 3; j++)
{
p2 = malloc(128 * sizeof(char));
memset(p2, 0, 128 * sizeof(char));
}
p1.stuname = p2;
}
}
return p1;
}
// 释放创建的空间
void freeTArray(struct Teacher * tArray, int num)
{
int i = 0;
if (tArray == NULL)
{
return;
}
// 释放 为*a_name申请的空间
for (i = 0; i < num; i++)
{
if (tArray.a_name != NULL) //为什么这里需要释放
{
free(tArray.a_name);
}
// 释放 为**stuname申请 的手工二维空间
if (tArray.stuname != NULL)
{
int i1 = 0, j1 = 0;
for (i1 = 0; i1 < 3; i1++)
{
if (tArray.stuname != NULL)
{
free(tArray.stuname);
}
}
free(tArray.stuname);
}
// malloc怎么申请的 就要怎么释放;只能拿到malloc返回的地址才能去释放啦
/* if (tArray.name != NULL) //这个地方需要自己释放吗?(不需要,结构图是一块申请的,要一块释放)
{
free(tArray.name);
}
*/
}
if (tArray != NULL)
{
free(tArray);
tArray = NULL; //垃圾话语
}
}
void main()
{
int i = 0, j = 0;
struct Teacher *pArray = createTArray1(3);
if (pArray == NULL)
{
return;
}
//这里是结构体数组,tArray是首元素的地址,他的类型是首元素的类型,struct Teacher *;
//tArray是第一个结构体的变量名
struct Teacher tArray;
for (i = 0; i < 3; i++)
{
printf("\n请输入age:");
scanf("%d", &pArray.age);
printf("\n请输入name:");
scanf("%s", pArray.name);
printf("\n请输入a_name:");
scanf("%s", pArray.a_name);
char **p2 = pArray.stuname;
for (j = 0; j < 3; j++)
{
printf("\n请输入学生的名字:");
scanf("%s", p2);
}
}
printf("排序之前:\n");
printfArray(pArray, 3);
sortArray(pArray, 3);
printf("\n排序之后:\n");
printfArray(pArray, 3);
freeTArray(pArray, 3);
system("pause");
}
2、深浅copy
浅拷贝:指的是在进行结构体的拷贝时,由于结构体中有带内存块的指针变量,而拷贝时只是进行单纯的赋值操作,导致被复制的结构体所挂内存的丢失或没被创建。
深拷贝:即在拷贝时避免的结构体内指针所挂内存块旳丢失或未创建。
浅拷贝容易造成内存的多次释放和内存的泄露。
代码示例:
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
struct AdTeacher
{
char name;
char *a_name;
int age;
};
// 手工创建结构体数组
struct AdTeacher * createTArray2(int count)
{
int i = 0, j = 0;
struct AdTeacher*p1 = (struct AdTeacher *)malloc(count * sizeof(struct AdTeacher));
if (p1 == NULL)
{
return NULL;
}
for (i = 0; i < count; i++)
{
memset(&p1, 0, sizeof(struct AdTeacher));
memset(p1 + i, '0', sizeof(struct AdTeacher)); // 和上面等价
p1.a_name = (char*)malloc(128 * sizeof(char));// 开辟空间给a_name
memset(p1.a_name, 0, 128 * sizeof(char)); //为自己开辟的空间赋初值
}
return p1;
}
// 释放创建的空间
void freeTArray2(struct AdTeacher * tArray, int num)
{
int i = 0;
if (tArray == NULL)
{
return;
}
// 释放 为*a_name申请的空间
for (i = 0; i < num; i++)
{
if (tArray.a_name != NULL) //为什么这里需要释放
{
free(tArray.a_name);
}
}
if (tArray != NULL)
{
free(tArray);
tArray = NULL; //垃圾话语
}
}
// 深拷贝
void deepCopy(struct AdTeacher *from, struct AdTeacher *to)
{
memcpy(to, from, sizeof(struct AdTeacher));
to->a_name = (char *)malloc(128);
strcpy(to->a_name, from->a_name);
}
void main()
{
int i = 0;
//struct AdTeacher t1;
//struct AdTeacher t2;
struct AdTeacher* p1 = createTArray2(1);
struct AdTeacher* p2 = createTArray2(1);
printf("\n请输入age:");
scanf("%d", &(p1.age));
printf("\n请输入name:");
scanf("%s", p1->name);
printf("\n请输入a_name:");
scanf("%s", p1.a_name);
//浅拷贝
// (*p2) = (*p1);
//编译器机械的=赋值,浅拷贝, 会导致p2和p1中的*a_name同时都指向p1中*a_name申请的内存空间
//导致p1中*a_name在释放时释放两次,而p2中*a_name没有被释放。
//自建函数来实现深拷贝
deepCopy(p1, p2);
freeTArray2(p1, 1);
freeTArray2(p2, 1);
system("pause");
}
页:
[1]