本文约3000字,主要讲了结构体和共用体,内容接上一节。包括指向结构体类型数据的指针、结构指针变量作函数参数和动态存储分配( malloc函数、 calloc函数和free函数)
带你进入C语言的世界,入门C语言,后边将持续更新。可以收藏学习。想了解定义结构体类型变量的方法、结构体变量的引用、结构体变量的初始化和结构体数组等,请点击该处跳转阅读。
本文全干货,新手必备,感谢你的阅读,祝你学有所成,生活愉快!
一、指向结构体类型数据的指针
一个结构体变量的指针就是该结构体变量所占据的内存段的起始地址。可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。指针变量也可以用来指向结构体数组中的元素。
结构指针变量说明的一般形式为:struct 结构名 *结构指针变量名
例如,在前面的例题中定义了stu这个结构,如要说明一个指向stu的指针变量pstu,可写为:
struct stu *pstu;
当然也可在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构指针变量也必须要先赋值后才能使用。
赋值是把结构变量的首地址赋予该指针变量,不能把结构名赋予该指针变量。如果boy是被说明为stu类型的结构变量,则:
pstu=&boy 是正确的。
pstu=&stu 是错误的。
因为,结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不对它分配内存空间。只有当某变量被说明为这种类型的结构时,才对该变量分配存储空间。因此上面&stu这种写法是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就能更方便地访问结构变量的各个成员。
其访问的一般形式为:
(*结构指针变量).成员名
或为:
结构指针变量->成员名
例如: (*pstu).num 或者: pstu->num
案例:
#include
struct stu
{ int num;
char *name;
char sex;
float score;
} boy1 = {102, "Fishc", 'M', 78.5};
main()
{ struct stu *pstu;
pstu = &boy1;
printf("Number = %dName = %s", boy1.num, boy1.name);
printf("Sex = %cScore = %f", boy1.sex, boy1.score);
printf("Number = %dName = %s", (*pstu).num, (*pstu).name);
printf("Sex = %cScore = %f", (*pstu).sex, (*pstu).score);
printf("Number = %dName = %s", pstu->num, pstu->name);
printf("Sex = %cScore = %f", pstu->sex, pstu->score); }
二、结构指针变量作函数参数
将一个结构体变量的值传递给另一个函数,有3个方法:
(1)用结构体变量的成员作参数
(2)用结构体变量作实参
(3)用指向结构体变量(或数组)的指针作实参,将结构体变量(或数组)的地址传给形参
例题:有一个结构体变量stu,内含学生学号、姓名和3门课程的成绩。通过调用函数print中将它们输出。
先用结构体变量作函数参数
#include
#include
struct student
{
int num;
char *name;
float score[3];
};
void print(struct student);
main()
{
struct student stu;
stu.num = 8;
stu.name = "Fishc.com!";
stu.score[0] = 98.5;
stu.score[1] = 99.0;
stu.score[2] = 99.5;
print( stu );
}
void print( struct student stu )
{
printf("num : %d", stu.num);
printf("name : %s", stu.name);
printf("score_1 : %5.2f", stu.score[0]);
printf("score_2 : %5.2f", stu.score[1]);
printf("score_3 : %5.2f", stu.score[2]);
printf("");
}
改用指向结构体变量的指针作实参
#include
#include
struct student
{
int num;
char name[20];
float score[3];
};
void print(struct student *);
main()
{
struct student stu;
stu.num = 8;
strcpy(stu.name, "Fishc.com!");
stu.score[0] = 98.5;
stu.score[1] = 99.0;
stu.score[2] = 99.5;
print( &stu );
}
void print( struct student *p )
{
printf("num : %d", p -> num);
printf("name : %s", p -> name);
printf("score_1 : %5.2f", p -> score[0]);
printf("score_2 : %5.2f", p -> score[1]);
printf("score_3 : %5.2f", p -> score[2]);
printf("");
}
三、动态存储分配
在数组一章中,曾介绍过数组的长度是预先定义好的,在整个程序中固定不变。C语言中不允许动态数组类型。例如:int a[n];是错的!
![dc1a5fe42559757fe7c7f1c425168e36.png](https://i-blog.csdnimg.cn/blog_migrate/c23b86f74097001afa9fb56346ab7329.jpeg)
用变量表示长度,想对数组的大小作动态说明,这是错误的。但是在实际的编程中,往往会发生这种情况,即所需的内存空间取决于实际输入的数据,而无法预先确定。
所以对于这种问题,用数组的办法很难解决!
为了解决上述问题,C语言提供了一些内存管理函数,这些内存管理函数可以按需要动态地分配内存空间,也可把不再使用的空间回收待用,为有效地利用内存资源提供了手段。
常用的内存管理函数有以下三个:
(1)分配内存空间函数 malloc、calloc
(2) 释放内存空间函数 free
1.malloc函数
函数原型为 void *malloc(unsigned int size);
其作用是在内存的动态存储区中分配一个长度为size的连续空间(size是一个无符号数)。此函数的返回值是一个指向分配域起始地址的指针(类型为void)。如果此函数未能成功地执行(例如内存空间不足),则返回空指针(NULL)。
2.calloc函数
函数原型为 void *calloc(unsigned n, unsigned size);
其作用是在内存的动态存储区中分配n个长度为size的连续空间。函数返回一个指向分配域起始地址的指针;如果分配不成功,返回NULL。用calloc函数可以为一维数组开辟动态存储空间,n为数组元素个数,每个元素长度为size。
3.free函数
函数原型为 void free(void *p);
其作用是释放由p指向的内存区,使这部分内存区能被其他变量使用。p是最近一次调用calloc或malloc函数时返回的值。free函数无返回值。
感谢您的阅读,希望有所收获!会持续更新!下一节将讲链表,贼难!