大家好,又见面了,我是你们的朋友全栈君。
文章目录
- 结构体概述
- 结构体指针
- 动态存储分配
- <1>.malloc函数
- <2>.calloc函数
- <3>.free函数
- 动态存储分配
结构体概述
问题定义:有时需要将不同类型的数据组合成一个有机的整体,以便于使用,就类似于sql中的存储一样,随着语言层次的增高封装性是越来越大的。如:
代码语言:javascript复制int num;
char name[20];
char sex;
int age;
char addr[30];
Jetbrains全家桶1年46,售后保障稳定
定义结构的一般形式为: struct 结构名{ 成员列表 };
成员列表由若干个成员构成,每个成员都是该结构的组成部分,对每个成员必须做类型说明,其形式为: 类型说明符 成员名; 例如说
代码语言:javascript复制struct student{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}
可以采用以下三种方法定义结构体类型变量:
- (1)先声明结构体类型再定义变量名 例如:struct(类型名) student(结构体) student1(变量名),student2(变量名); 定义了student1和student2为struct student类型的变量,即他们具有struct student类型的结构
- (2)在声明类型的同时定义变量这种形式的定义的一般形式为: struct 结构体名{ 成员列表 }变量名; 例如:
struct student{
int num;
char name[20];
char sex;
int age;
float score;
char addr[30];
}student1,student2
在定义了结构体变量后,系统会为其分配内存单元。例如: student1和student2在内存中各占几字节? 答(4 20 1 4 4 30 = 63)
- (3)直接定义结构体类型变量其一般形式为: struct{ 成员列表 }变量名
现在我们直到了怎么构造一个结构体了,下面要说一下在结构体内引用另一个结构体的方法,也就是在结构体内嵌套另一个结构体
首先我们定义一个结构体date,由month,day,year组成 在定义说明变量boy1和boy2时,其中的成员birthday被说明为date结构类型。成员名可与程序中其他变量同名,互不干扰。
代码语言:javascript复制struct date{
int month;
int day;
int year;
};
struct {
int num;
char name[30];
char sex;
struct date birthday;
float score;
}boy1,boy2;
引用变量法则: (1)不能将一个结构体变量作为一个整体进行输入和输出。 应该这样引用:
代码语言:javascript复制int main() {
boy1.num = 01;
boy1.sex = 'M';
printf("%d,%c", boy1.num, boy1.sex);
}
对于结构体的基础语法说完了,下面来说结构体指针
结构体指针
一个结构体变量的指针就是该结构体变量所占据内存段的起始地址。 可以设一个指针变量,用来指向一个结构体变量,此时该指针变量的值是结构体变量的起始地址。 同时指针变量也可以用来指向结构体数组中的元素。 结构体指针变量说明的一般形式为: struct 结构名 *结构指针变量名 例如,在前面的例题中定义了stu这个结构,如果要说明一个指向stu的指针变量pstu,可写为 struct stu *pstu; 当然也可以在定义stu结构时同时说明pstu。与前面讨论的各类指针变量相同,结构体指针变量也必须要先赋值才能使用 赋值就是把结构变量首地址赋予该指针变量,不能把结构名赋予该指针变量。 如果boy是被说明为stu类型的结构变量,则: pstu = &boy;是正确的 pstu = &stu;是错误的 因为结构名和结构变量是两个不同的概念,不能混淆。结构名只能表示一个结构形式,编译系统并不对他们分配内存空间,只有当某变量被说明为这种类型的结构时,才对该变量存储内存空间。 所以以上 pstu = &stu;是错误的,不可能去取一个结构名的首地址。有了结构指针变量,就更方便地访问结构变量的各个成员。 其访问的一般形式为: (*结构指针变量).成员名 或为: 结构指针变量->成员名 例如:(*pstu).num 或者:pstu->num
小案例
代码语言:javascript复制struct stu{
int num;
char *name;
char sex;
float score;
}boy1 = {
006,"zhangzhang",'1',69.6};
int main() {
struct stu *pstu;
pstu = &boy1;
printf("%d,%sn", boy1.num, boy1.name);
printf("%d,%sn", (*pstu).num, (*pstu).name);
printf("%d,%sn", pstu->num, pstu->name);
}
例题:有一个结构体变量stu,内含学生学号、姓名和三门学科的成绩,通过调用函数print使他们输出
代码语言:javascript复制struct student{
int num;
char *name;
int score[3];
};
void print(struct student stu,struct student *pstu){
printf("num:%dn",stu.num);
printf("name:%sn", stu.name);
printf("score[0]:%dn", pstu->score[0]);
printf("score[1]:%dn", (*pstu).score[1]);
printf("score[2]:%dn", (*pstu).score[2]);
}
int main() {
struct student *p;
struct student stu;
stu.num = 007;
p->name = "zhangzhang";
(*p).score[0] = 59;
(*p).score[1] = 60;
(*p).score[2] = 61;
print(stu,p);
// struct stu *pstu;
// pstu = &boy1;
//
// printf("%d,%sn", boy1.num, boy1.name);
//
// printf("%d,%sn", (*pstu).num, (*pstu).name);
//
// printf("%d,%sn", pstu->num, pstu->name);
}
动态存储分配
在数组一章中,曾介绍过数组的长度是预先定义好的,在整个程序中固定不变。在C语言中不允许动态数组类型。例如:a[n]就是错误的,必须要用一个实际的数字表示数组长度,但是在实际开发中,往往会发生这种情况,即所需要的内存空间取决于实际输入的数据,而无法预先确定。对于以上问题,使用数组的办法很难解决,只能通过内存管理函数,动态分配内存空间。 常用的内存管理函数有以下三个: 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函数的时候返回的值。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/203524.html原文链接:https://javaforall.cn