这个结构体不难理解,难理解的是后面结构体指针数组。多多观看,主包也在学习,可能解释的并不是特别明了,想要多多了解的可以多看看相关教学视频。
1.基本认识
在我们之前的开发中,会遇到一个目标需要多个属性来描述,例如学生:名字,性别,身高,体重等等。用单一的数据类型无法进行准确描述。所以此时就需要构造数据类型:结构体。
结构体就我个人理解而言:是一个融合了多种基本数据类型的复合数据类型。
2.结构体数据类型的格式
结构体声明 一般是在main函数前面
结构体声明有两种格式,一种是匿名声明方法,没有小名/别称。另一种是起了一个别称,可以叫别名声明法(主包自己想的)后续可以使用这个别称来创造结构体。
格式1:
struct student
{
char name[32];
char gender;
int id;
float score;
}; //匿名声明方法 没有小名
格式2:
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
}STU; //给struct student2 起起了个别名 叫STU
3.结构体变量
3.1结构体:是一种复合数据的数据类型
变量的声明: 数据类型 变量名 = 初始化赋值;
结构体变量的声明:
结构体类型 变量名 = {初始化赋值};
#include<stdio.h>
struct student
{
char name[32];
char gender;
int id;
float score;
};
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
}STU;
int main(int argc, char const *argv[])
{
//匿名,没有小名 所以用struct student 直接声明变量
struct student stu1 = {"xxx",'M',10086,99.3F}; //要与成员一一对应
//可以用 结构体变量名 + . 的方式取出对应的成员属性
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu1.name,stu1.gender,stu1.id,stu1.score);
//用别名 STU声明一个stu2 等价于 struct student2 stu2;
STU stu2 = {"yyy",'M',10010,99.1F};
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu2.name,stu2.gender,stu2.id,stu2.score);
return 0;
}
3.2结构体的赋值方法
方法一:
通过像是对数组赋值一样,对结构体进行赋值,赋值时要根据不同的数据类型赋值。
#include<stdio.h>
struct student
{
char name[32];
char gender;
int id;
float score;
};
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
}STU;
int main(int argc, char const *argv[])
{
//匿名,没有小名 所以用struct student 直接声明变量
struct student stu1 = {"xxx",'M',10086,99.3F}; //要与成员一一对应
//可以用 结构体变量名 + . 的方式取出对应的成员属性
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu1.name,stu1.gender,stu1.id,stu1.score);
return 0;
}
方法二:单一赋值,尤其是name;strcpy是一个字符串复制函数。在linux中可以使用 man 命令查看不同函数的使用方法。eg:man strcpy。
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU stu1;
strcpy(stu1.name, "xxx");
stu1.gender = 'M';
stu1.id = 10000;
stu1.score = 99.8F;
// 可以用 结构体变量名 + . 的方式取出对应的成员属性
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu1.name, stu1.gender, stu1.id, stu1.score);
}
3.3结构体指针变量
回顾:
指针变量的声明:
数据类型 *指针变量名 = 初始化地址;
int *p = NULL;
结构体指针变量:
结构体类型 *结构体变量名 = 初始化地址;
结构体指针变量的一个例子:
#include <stdio.h>
#include <string.h>
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU stu1 = {"lucy", 'F', 99999, 100.0F};
STU *p = &stu1; // p指向 stu1的首地址
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
(*p).name, (*p).gender, (*p).id, (*p).score); //*p ==>stu1
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu1.name, stu1.gender, stu1.id, stu1.score);
// 可以通过 指针+ -> 取出对应的属性
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
p->name, p->gender, p->id, p->score);
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
(&stu1)->name, (&stu1)->gender, (&stu1)->id, (&stu1)->score);
return 0;
}
4.结构体动态内存开辟
4.1结构体成员动态内存分配
这里我们来name进行动态内存分配
将name定义为指针变量,用来承接动态内存分配出来的地址
typedef struct student2
{
char *name; //指针,用来承接动态内存分配出来的地址
char gender;
int id;
float score;
} STU;
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student2
{
char *name;
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU stu1;
stu1.gender = 'M';
stu1.id = 99999;
stu1.score = 100.0F;
stu1.name = (char *)malloc(sizeof("漫夜"));
strcpy(stu1.name,"漫夜");
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu1.name, stu1.gender, stu1.id, stu1.score);
if (stu1.name != NULL ) //防御性代码,避免操作到无权限的指针
{
free(stu1.name);
stu1.name = NULL;
}
return 0;
}
4.2结构体动态内存分配
将结构体动态内存分配之后,再将name动态内存开辟;
通俗的理解就是:开辟一个结构体空间之后,再将结构体中的name开辟出内存空间。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student2
{
char *name;
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU *stu = NULL;
stu = (STU *)malloc(sizeof(STU)); //先开辟结构体空间
stu->name = (char *)malloc(sizeof("漫夜")); //再开辟成员空间
stu->gender = 'M';
stu->id = 10001;
stu->score = 99.9F;
strcpy(stu->name, "漫夜");
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu->name, stu->gender, stu->id, stu->score);
if (stu->name != NULL) //先释放结构体成员指针
{
free(stu->name);
stu->name = NULL;
}
if (stu != NULL) // 再释放结构体指针。如果先释放结构体指针,那么结构体成员指针将没有操作权限
{
free(stu);
stu = NULL;
}
return 0;
}
5.结构体数组

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU stu[3];
for (int i = 0; i < 3; i++)
{
printf("请依次输入第 %d个学生的信息,姓名 性别 id 成绩,空格隔开\n",i);
scanf("%s %c %d %f",stu[i].name,&stu[i].gender,&stu[i].id,&stu[i].score);
}
for (int i = 0; i < 3; i++)
{
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu[i].name, stu[i].gender, stu[i].id, stu[i].score);
}
return 0;
}
6.结构体指针 数组
定义一个数组,里面存放的都是结构指针
6.1数组全在栈区,结构体在堆区(重要!)

一个一级指针,指向数组第一个元素地址
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
STU *stu[3] = {NULL}; // 初始化赋值,都指向NULL 数组在栈区
for (int i = 0; i < 3; i++)
{
stu[i] = (STU *)malloc(sizeof(STU)); // 数组中每个成员在堆区
}
for (int i = 0; i < 3; i++)
{
printf("请依次输入第 %d个学生的信息,姓名 性别 id 成绩,空格隔开\n", i);
scanf("%s %c %d %f", stu[i]->name, &stu[i]->gender, &stu[i]->id, &stu[i]->score);
}
for (int i = 0; i < 3; i++)
{
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu[i]->name, stu[i]->gender, stu[i]->id, stu[i]->score);
}
for (int i = 0; i < 3; i++)
{
if (stu[i] != NULL)
{
free(stu[i]);
stu[i] = NULL;
}
}
return 0;
}
6.2数组在堆区,结构体在堆区(难点,但不是重点,理解为主)

一个二级指针,指向数组地址的地址,有点难理解。
就是一个数组中存放着地址,这个数组中的地址指向一级指针的地址。
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
typedef struct student2
{
char name[32];
char gender;
int id;
float score;
} STU;
int main(int argc, char const *argv[])
{
int capacity = 3;
STU ** stu = (STU**)malloc(capacity*sizeof(STU*));
for (int i = 0; i < 3; i++)
{
stu[i] = (STU *)malloc(sizeof(STU)); // 数组中每个成员在堆区
}
for (int i = 0; i < 3; i++)
{
printf("请依次输入第 %d个学生的信息,姓名 性别 id 成绩,空格隔开\n", i);
scanf("%s %c %d %f", stu[i]->name, &stu[i]->gender, &stu[i]->id, &stu[i]->score);
}
for (int i = 0; i < 3; i++)
{
printf("NAME:%s GENDER:%c ID:%d SCORE:%0.1f\n",
stu[i]->name, stu[i]->gender, stu[i]->id, stu[i]->score);
}
for (int i = 0; i < 3; i++)
{
if (stu[i] != NULL)
{
free(stu[i]);
stu[i] = NULL;
}
}
if (stu !=NULL)
{
free(stu);
stu = NULL;
}
return 0;
}
537

被折叠的 条评论
为什么被折叠?



