[day05]二级指针分配内存,释放内存、防止野指针的手段、结构体操作(中嵌一二级指针,分配内存,释放内存)
1.二级指针分配内存,释放内存
主要围绕二级指针的第三种内存模型(自己构造内存) |
1 #include <stdio.h> 2 3 #define PAR_CNT 10 4 #define CHI_CNT 2 5 6 /*创建10个二级指针,每个二级指针挂2个一级指针*/ 7 char ** create_mem() 8 { 9 char **pParent = NULL; 10 int i; 11 12 pParent = (char **)malloc(PAR_CNT * sizeof(char *)); 13 if (pParent == NULL) { 14 printf("func malloc() err \n"); 15 return pParent; 16 } 17 18 for (i=0; i<CHI_CNT; i++) { 19 pParent[i] = (char *)malloc(CHI_CNT * sizeof(char)); 20 if (pParent[i] == NULL) { 21 printf("func malloc for pParent[%d] is err \n", i); 22 return NULL; 23 } 24 } 25 return pParent; 26 } 27 28 int free_mem(char ** pArray) 29 { 30 /*先释放一级指针,也就是孩子指针内存*/ 31 int i; 32 int ret = 0; 33 34 if (pArray == NULL) { 35 ret = -1; 36 printf("不需要释放!\n"); 37 return ret; 38 } 39 40 for (i=0; i<CHI_CNT; i++) { 41 if (pArray[i] == NULL) { 42 ret = -1; 43 printf("不需要释放!\n"); 44 return ret; 45 } 46 47 free(pArray[i]); 48 //pArray[i] = NULL; /*这是一条垃圾语句*/ 49 50 } 51 52 /*释放二级指针指向的内存块*/ 53 free(pArray); 54 //pArray = NULL; /*同样这也是一条垃圾语句*/ 55 56 return ret; 57 } 58 59 int main(void) 60 { 61 char **pArray = NULL; 62 int ret = 0; 63 64 pArray = create_mem(); 65 ret = free_mem(pArray); 66 67 return 0; 68 } |
注意:实参和形参是两个不同的东西,在释放的函数中释放之后置NULL是没有意义的。 |
2.防止野指针的手段
防止野指针的手段 |
|
3.结构体操作
结构体中嵌入一级,二级指针,分配内存,被调函数使用二级指针置NULL。 |
1 #include <stdio.h> 2 3 #define TCH_CNT 3 // 3名老师 4 #define STU_CNT 2 // 每名老师2学生 5 #define NAM_LEN 20 6 7 typedef struct _Teacher 8 { 9 char name[NAM_LEN]; //20+4+4+4=32 10 int age; 11 char *a_name; //别名 12 char **s_name; // 学生的名字 13 }Teacher; 14 15 //这里使用二级指针参数来把分配的内存传出来好了 16 int create_mem(Teacher **t) 17 { 18 int ret = 0; 19 int i, j; 20 21 *t = (Teacher *)malloc(TCH_CNT * sizeof(Teacher)); 22 23 if (*t == NULL) { 24 ret = -1; 25 printf("func malloc() err: %d\n", ret); 26 return ret; 27 } 28 29 //给这三名老师的名字和年龄赋值 30 for (i=0; i<TCH_CNT; i++) { 31 sprintf((*t+i)->name, "老师%d", i+1); 32 (*t+i)->age = (i+1)*10; 33 34 //给一级指针的别名分配内存 35 (*t+i)->a_name = (char *)malloc(NAM_LEN * sizeof(char)); 36 //别名赋值 37 sprintf((*t+i)->a_name, "%d老师", i+1); 38 39 //给二级指针的老师的学生分配内存 40 (*t+i)->s_name = (char **)malloc(STU_CNT * sizeof(char *)); 41 for (j=0; j<STU_CNT; j++) { 42 (*t+i)->s_name[j] = (char *)malloc(NAM_LEN * sizeof(char)); 43 //给每个老师的每位学生赋值 44 sprintf((*t+i)->s_name[j], "第%d位老师的第%d位学生", i+1, j+1); 45 } 46 } 47 48 return ret; 49 } 50 51 void print_str(Teacher *t) 52 { 53 int i, j; 54 55 for (i=0; i<TCH_CNT; i++) { 56 printf("%s ", (t+i)->name); 57 printf("%d ", t[i].age); 58 printf("%s ", (t+i)->a_name); 59 for (j=0; j<STU_CNT; j++) { 60 printf("%s ", (t+i)->s_name[j]); 61 } 62 printf("\n"); 63 } 64 } 65 66 //这里使用二级指针刚好释放了直接置为NULL 67 void free_mem(Teacher **t) 68 { 69 int i, j; 70 71 if (*t != NULL) 72 { 73 for(i=0; i<TCH_CNT; i++) { 74 //释放二级指针的学生姓名的空间 75 for (j=0; j<STU_CNT; j++) { 76 if ((*t+i)->s_name != NULL) { 77 if ((*t+i)->s_name[j] != NULL) { 78 free((*t+i)->s_name[j]); 79 (*t+i)->s_name[j] = NULL; 80 } 81 82 free((*t+i)->s_name); 83 (*t+i)->s_name = NULL; 84 } 85 } 86 87 //释放一级指针的别名的空间 88 if ((*t+i)->a_name != NULL) { 89 free((*t+i)->a_name); 90 (*t+i)->a_name = NULL; 91 } 92 } 93 94 printf("t不为NULL,我要释放!\n"); 95 free(*t); 96 *t = NULL; 97 } 98 } 99 100 int main(void) 101 { 102 Teacher *pt = NULL; 103 104 //printf("%d\n", sizeof(t)); 105 create_mem(&pt); 106 107 //printf("%d\n", sizeof(*pt)); 108 print_str(pt); 109 110 free_mem(&pt); 111 printf("&pt=%d\n", pt); // pt的值已经置NULL了 112 //free_mem(&pt); // 因为使用二级指针,这里就算是调用释放多次,里面也不会执行了 113 return 0; 114 } |
要想不适用返回值返回,如果主调函数是一级指针,那么参数请使用二级指针。分配内存的顺序和释放内存的顺序相反,此代码可能还不完善。 |