C语言:结构体中一级指针和二级指针的创建与释放示例

http://blog.csdn.net/Bixiwen_liu/article/details/53610952

这几天把C语言巩固了一下,作为一门最基本的编程语言,C语言还是相当基础和非常重要的,个人认为C语言还是很有必要学好吃透的。

今天写的话题是结构体结构体中一级指针和二级指针的创建与释放,以一个例子来说明,笔者这里自己敲得代码,虽然用C语言几年了,但是有的东西还是会遗忘。笔者敲代码过程中也是有bug出现的,经过调试也找到了bug所在,不得不说,巩固也是很重要的。而结构体作为C语言一部分也是很重要的,指针作为C语言的半壁江山也保持着其重要地位。代码不是很长,但里面有很多细节的考虑,特别是一级指针和二级指针的内存的申请和释放。

代码的主要表达是:有三个老师,每个老师都有属性名字,年龄,别名,编号,以及有三个学生名字。老师名字(name)的内存分配是在栈区,别名(alisname)和学生名(stuname)的内存分配是在堆区。个人认为C语言的内存四区(栈区,堆区,全局区,代码区)很重要,所以喜欢从内存四区的角度看代码,对理解C语言的本质是重要,也是理解bug所在的重要原因。

下面是示例代码:


[cpp] view plain copy
  1. // 结构体 示例  
  2. #include "stdio.h"  
  3. #include "stdlib.h"  
  4. #include "string.h"  
  5.   
  6. typedef struct Teacher // 定义一个结构体,名称为Teacher  
  7. {  
  8.     char name[64];  
  9.     int age;  
  10.     char *alisname;//别名  
  11.     char **stuname;  
  12.     int id;  
  13. }Teacher;  
  14.   
  15. int createTeacher(Teacher **pT, int num)  
  16. {  
  17.     int i = 0;  
  18.     int j = 0;  
  19.     int ret = 0;  
  20.     Teacher *tmp = NULL;  
  21.   
  22.     tmp = (Teacher *)malloc(num * sizeof(Teacher));  
  23.     if (tmp == NULL)  
  24.     {  
  25.         ret = -1;  
  26.         printf("malloc err: %d\n",ret);  
  27.         return ret;  
  28.     }  
  29.     memset(tmp, 0, num * sizeof(Teacher));  
  30.   
  31.     for (i = 0; i < num; i++)  
  32.     {  
  33.         char **myp = NULL;  
  34.           
  35.         //先创建一级指针  
  36.         tmp[i].alisname = (char *)malloc(60);  
  37.         if ( tmp[i].alisname == NULL)  
  38.         {  
  39.             ret = -2;  
  40.             printf("malloc tmp[i].alisname err: %d\n",ret);  
  41.             return ret;  
  42.         }  
  43.   
  44.         //再创建二级指针  
  45.         myp = (char **)malloc(3 * sizeof(char *));  
  46.         if (myp == NULL)  
  47.         {  
  48.             ret = -3;  
  49.             return ret;  
  50.         }  
  51.         for (j = 0; j < 3; j++)  
  52.         {  
  53.             myp[j] = (char *)malloc(60);  
  54.             if (myp[j] == NULL)  
  55.             {  
  56.                 ret = -4;  
  57.                 return ret;  
  58.             }  
  59.         }  
  60.         tmp[i].stuname = myp;  
  61.     }  
  62.   
  63.     *pT = tmp;  
  64.     return ret;  
  65. }  
  66.   
  67. int printTeacherandStu(Teacher *p, int num)  
  68. {  
  69.     int i = 0;  
  70.     int j = 0;  
  71.     int ret = 0;  
  72.     Teacher *tmp = NULL;  
  73.   
  74.     if (p == NULL)  
  75.     {  
  76.         ret = -1;  
  77.         printf("p is null : %d\n",ret);  
  78.         return ret;  
  79.     }  
  80.     tmp = p;  
  81.   
  82.     for (i = 0; i < num; i++)  
  83.     {  
  84.         char **myp = NULL;  
  85.           
  86.         printf("teacher name: %s\n",tmp[i].name);  
  87.         printf(" teacher alisname: %s\n",tmp[i].alisname);  
  88.   
  89.         printf("  student's name:  ");  
  90.         myp = tmp[i].stuname;  
  91.         for (j = 0; j < 3; j++)  
  92.         {  
  93.             printf("%s  ",myp[j]);  
  94.         }  
  95.         printf("\n");     
  96.     }  
  97.     return ret;  
  98.   
  99. }  
  100.   
  101. void FreeTeacher(Teacher *p, int num)  
  102. {  
  103.     int i = 0;  
  104.     int j = 0;  
  105.     Teacher *tmp = NULL;  
  106.   
  107.     tmp = p;  
  108.   
  109.     for(i = 0; i < num; i++)  
  110.     {  
  111.         char **myp = NULL;  
  112.         //先释放以及指针  
  113.         if (tmp[i].alisname != NULL)  
  114.         {  
  115.             free(tmp[i].alisname);  
  116.         }  
  117.   
  118.         //再释放二级指针  
  119.         if (tmp[i].stuname != NULL)  
  120.         {  
  121.             myp = tmp[i].stuname;  
  122.             for (j = 0; j < 3; j++)  
  123.             {  
  124.                 if (myp[j] != NULL)  
  125.                 {  
  126.                     free(myp[j]);  
  127.                 }  
  128.             }  
  129.             free(myp);  
  130.             tmp[i].stuname = NULL;  
  131.         }     
  132.     }  
  133.     free(tmp);  
  134. }  
  135.   
  136. int main()  
  137. {  
  138.     int ret = 0;  
  139.     int i = 0;  
  140.     int j = 0;  
  141.     int num = 3;  
  142.     Teacher *pArray = NULL;  
  143.   
  144.     ret = createTeacher(&pArray, num);  
  145.     if (ret != 0)  
  146.     {  
  147.         printf("func createTeacher() err: %d\n",ret);  
  148.         return ret;  
  149.     }  
  150.   
  151.     for (i = 0; i < num; i++)  
  152.     {  
  153.         printf("\nplease input teacher's name:");  
  154.         scanf("%s",pArray[i].name);  
  155.   
  156.         printf("\n please input teacher's age:");  
  157.         scanf("%d",&(pArray[i].age));  
  158.   
  159.         printf("\n please input teacher's alsname:");  
  160.         scanf("%s",pArray[i].alisname);  
  161.   
  162.         for (j = 0; j < 3; j++)  
  163.         {  
  164.             printf("\n  please input student name:");  
  165.             scanf("%s",pArray[i].stuname[j]);  
  166.         }  
  167.     }  
  168.   
  169.     ret = printTeacherandStu(pArray, num);  
  170.     if (ret != 0)  
  171.     {  
  172.         ret = -2;  
  173.         printf("func printTeacherandStu() err: %d\n",ret);  
  174.         return ret;  
  175.     }  
  176.   
  177.     FreeTeacher(pArray, num);  
  178.     return 0;  
  179. }  

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/384030.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

带环迷宫求最短路径

前面介绍了简单的迷宫求解问题, 今天我们就对带环迷宫求出它的最短路径 1.首先来看一个带环迷宫的简单地图 在这张迷宫地图中,我们规定入口点的位置entry的坐标是 (0, 1), 同时, 我们给入口点传一个非法坐标,作为入口点的前一个位置(-1, -1). 接下来的思路就和上一篇的思路是一…

UVa1583

【题目描述】 传送门 【题目分析】 我以为很简单就写了一个暴力没有想到超时了。应该是T是非常大的所以必须得打表&#xff0c;将所有的结果都储存起来然后直接输出。 以后遇到这种可以一下算出所有结果的多组数据最好还是算出所有的结果然后再输出答案。 【AC代码】 #inc…

C 结构体嵌套一级指针 二级指针 动态分配内存

https://blog.csdn.net/xielinhua88/article/details/51364623 点击打开链接 #define _CRT_SECURE_NO_WARNINGS #include <stdlib.h> #include <string.h> #include <stdio.h> //结构体嵌套一级指针 二级指针 动态分配内存 typedef struct _Teacher { int ag…

线程的同步与互斥

1. 互斥量 在Linux 下线程使用的都是局部变量, 而我们知道, 每一个线程都独立拥有自己的一个栈, 而这些局部便令就在栈中,而线程的创建就是为了实现通信, 此时线程之间无法共享这些变量     为了使得线程之间能够共享数据, 一次我们可以创建一个全局变量, 此时线程都在进程…

二级指针与指针数组的关系

http://blog.csdn.net/shuaishuai80/article/details/6129742 #include <stdio.h> void test(char *argv[]); int main(void) { char *argv[3]{{"abcdefg"},{"1234567"},{"q1w2e3r"}}; test(argv); /*调用指针数组…

UVa1584

【题目描述】 传送门 【题目分析】 也是一道简单的模拟题&#xff0c;1A嘿嘿嘿。 再看书发现和书上的做法差不多。 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstd…

cf#582div3 D——暴力

【题目描述】 The only difference between easy and hard versions is the number of elements in the array.You are given an array a consisting of n integers. In one move you can choose any ai and divide it by 2 rounding down (in other words, in one move you c…

C语言 可变参数

http://www.cnblogs.com/zhanggaofeng/p/6434554.html //可变参数 #include <stdio.h> #include <stdlib.h> #include <string.h> //引用头文件 #include <stdarg.h>/* va_list用于声明一个变量&#xff0c;我们知道函数的可变参数列表其实就是一个字符…

UVa1585

【题目描述】 传送门 【题目分析】 氵 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector>u…

c语言经典算法——查找一个整数数组中第二大数

https://www.cnblogs.com/dootoo/p/4473958.html 题目&#xff1a; 实现一个函数&#xff0c;查找一个整数数组中第二大数。 算法思想&#xff1a; 设置两个变量max1和max2&#xff0c;用来保存最大数和第二大数&#xff0c;然后将数组剩余的数依次与这两个数比较&#xff0c;如…

进程间关系和守护进程

一. 进程组/作业/会话 1.进程组 每一个进程除了有一个进程ID之外, 还属于一个进程组. 进程是一个或多个进程的集合. 通常, 它们与同一个作业向关联, 可以接收来自同一个终端下的各种命令,信号. 每一个进程组都有唯一的进程组 ID. 每一个进程组都可以有一个组长进程. 组长进程的…

UVa1586

【题目描述】 传送门 【题目分析】 氵 【AC代码】 #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<queue> #include<cstdlib> #include<set> #include<map> #include<vector> …

猴子偷桃问题

http://blog.csdn.net/snow_5288/article/details/52561882 问题描述&#xff1a; /*有一群猴子&#xff0c;去摘了一堆桃子*/ /*商量之后决定每天吃剩余桃子的一半*/ /*当每天大家吃完桃子之后&#xff0c;有个贪心的小猴都会偷偷再吃一个桃子*/ /*按照这样的方式猴子们每天都…

UVa1225

【题目描述】 传送门 【题目分析】 做题做多了慢慢都忘记暴力了&#xff0c;想要快速算出来&#xff0c;找到规律&#xff0c;但是找来找去好复杂的都没有找到&#xff0c;然后写了一个不能再暴力的写法&#xff0c;就过了。。。 我还是觉得如果数据范围变成1e9那种级别的还…

linux 线程学习之条件变量

http://blog.csdn.net/hemmanhui/article/details/4417433 互斥锁&#xff1a;用来上锁。 条件变量&#xff1a;用来等待&#xff0c;当条件变量用来自动阻塞一个线程&#xff0c;直到某特殊情况发生为止。通常条件变量和互斥锁同时使用。 函数介绍&#xff1a; 1&#xff0e;…

UVa455

【题目描述】 传送门 【题目分析】 就是一个简单的暴力&#xff0c;只是需要注意输出格式比较毒瘤。 【AC代码】 #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<cmath> #i…

网络相关基础概念

一. 相关基础概念 1.计算机网络的特点 (1)连通性:计算机网络使得上网的用户都能够彼此相连, 好像用户的计算机可以直接相连     (2)资源共享:资源共享可以是信息共享, 软件共享, 硬件共享等等. 由于网络的存在, 使得用户感觉资源就在自己身边 2. 网络 网络是由若干结点和…

linux线程同步(2)-条件变量

https://www.cnblogs.com/yuuyuu/p/5140875.html linux线程同步(2)-条件变量 一.概述 上一篇&#xff0c;介绍了互斥量。条件变量与互斥量不同&#xff0c;互斥量是防止多线程同时访问共享的互斥变量来保护临界区。条件变量…

UVa227

【题目描述】 传送门 【题目分析】 题目的意思很简单&#xff0c;只是输入输出很毒瘤&#xff0c;我一开始用的fgets然后用scanf(" ")吃掉所有的空格和换行&#xff0c;可是这样有可能将迷宫的空格吃掉&#xff08;例如这个空格恰好在第一行第一列&#xff09;。 …

点对点数据链路层

数据链路层的主要功能将数据转换为相应的比特流使用的信道主要有点对点的信道方式(一对一的方式), 以及广播的信道方式 一. 点对点信道的数据链路层 1. 数据链路和数据帧 链路就是从一个结点连接到相邻结点的一段物理线路(有线或者无线), 期间不准有任何的交换结点, 因此两台…