之所以使用结构体,我个人认为,由于结构体能将不同类型数据组成整体,方便数据保存和使用。且结构体的定义是:有些数据既是相互关联的,又共同描述一个完整事物,如:一个学生的整体信息,学号、姓名、性别等。而我们做算法推理时,会涉及很多不同类型的参数,以及通常在复杂的网络中,参数们又自成一派。因此,结构体正好派上用场。所以本文简单介绍下,结构体的基础属性。
1.结构体的定义与内存分配
如下代码所示,定义了一个结构体数据类型,所谓数据类型就是固定大小内存块的别名,所以此时还没进行内存分配。
//定义了一个数据类型 。固定大小内存块的别名 还没有分配内存
typedef struct Teacher
{
char name[64];
int age ;
int id;
}Teacher;
只有用结构体数据类型定义结构体类型变量的时候,编译器才会分配内存。如下所示,是两种为结构体分配内存的方式。一种是分配在栈内存上,另一种则是分配在堆内存上。
//如下语句编译器就会分配内存在栈内存上
Teacher t1;
Teacher t2 = {"aaaa", 32, 02};
Teacher Array[3]; //定义三个结构体,分配三倍的栈内存空间。
//如下语句编译器就会分配内存在堆空间上
Teacher *pArray = NULL;
pArray = createTeacher(3);//在堆内存中分配3个结构体内存
Teacher * createTeacher(int num)
{
Teacher * tmp = NULL;
tmp = (Teacher *)malloc(sizeof(Teacher) * num); // same Teacher Array[3]
if (tmp == NULL)
{
return NULL;
}
return tmp;
}
2.结构体做函数参数
正常在较为庞大的工程中,我们会很注意我们对内存的使用,因为一不小心就会因内存溢出而导致程序崩溃。因此我们通常集中分配内存,统一管理。所以本例中利用单独在堆空间分配内存为例阐述。
#include <string.h>
#include <stdio.h>
typedef struct Teacher
{
char name[64];
int age ;
int id;
}Teacher;
void printTeacher(Teacher *array, int num)
{
int i = 0;
for (i=0; i<num; i++)
{
printf("age:%d \n", array[i].age);
}
}
void sortTeacer(Teacher *array, int num)
{
int i,j;
Teacher tmp;
for (i=0; i<num; i++)
{
for (j=i+1; j<num; j++)
{
if (array[i].age > array[j].age)
{
// 相当于对指针指向的位置的元素进行交换了,所以交换结果可以带出函数
tmp = array[i]; //=号操作 赋值操作
array[i] = array[j];
array[j] = tmp;
}
}
}
}
Teacher * createTeacher(int num)
{
Teacher * tmp = NULL;
tmp = (Teacher *)malloc(sizeof(Teacher) * num); // Teacher Array[3]
if (tmp == NULL)
{
return NULL;
}
return tmp;
}
void FreeTeacher(Teacher *p)
{
if (p != NULL)
{
free(p);
}
}
void main()
{
int i = 0;
//Teacher Array[3]; //在stack 分配内存
int num = 3;
Teacher *pArray = NULL;
pArray = createTeacher(num); //在heap 分配内存
for (i=0; i<num; i++)
{
printf("\nplease enter age:");
scanf("%d", & (pArray[i].age) );// C语言古典语法
}
printTeacher(pArray, num);
sortTeacer(pArray, num);
printf("after sort\n");
printTeacher(pArray, num);
FreeTeacher(pArray);
return ;
}
2.结构体做函数参数进阶
上述代码中用来为结构体分配内存的create函数,我们发现他返回了一个结构体指针。而我们在真正工作中,经常会使用另一种方式。如下代码段所示,我们会利用二级指针做函数参数,并在函数内修改一级指针。这样做的好处就是create函数可以返回一个是否成功创建内存空间的标识。当工程代码比较庞大时,这将显得极为重要。
int num = 3;
Teacher *pArray = NULL;
ret = createTeacher02(&pArray, num);
int createTeacher(Teacher **pT, int num)
{
int i = 0;
Teacher * tmp = NULL;
tmp = (Teacher *)malloc(sizeof(Teacher) * num);
if (tmp == NULL)
{
return -1;
}
memset(tmp, 0, sizeof(Teacher) * num);
for (i=0; i<num; i++)
{
tmp[i].alisname = (char *)malloc(60);
}
*pT = tmp; //二级指针 形参 去间接的修改 实参 的值
return 0;
}
网友评论