1.为什么要使用结构体
在c语言中有很多基础数据类型,在储存学生信息时需要用到多种基础数据类型比如成绩学号姓名,并且调用起来很麻烦,所以在c语言中专门有一种类型叫做结构体可以用来储存学生信息。
2.如何声明结构体
1.struct关键字
struct是一个关键字如果想使用结构体就要用struct声明具体形式如下
struct Student//结构体名称{
char *name;
int id;
int age;
};
2.结构体成员
结构体成员包括结构体类型(结构体名称),结构体成员,结构体变量
struct Student//结构体名称{
char *name;//成员
int id;//成员
int age;//成员
}stu1;//结构体变量
3.空结构体(了解)
空结构体指的是没有成员的结构体
struct student//结构体类型{
//TODO
}stu1;//结构体变量
4.匿名结构体(了解)
顾名思义匿名结构体就是没有名称的结构体
struct //结构体类型{
char *name;//成员
int id;//成员
int age;//成员
}stu1;//结构体变量
5.使用typedef
typedef是起到了便利结构体调用的作用,它可以重新命名结构体类型(结构体名称),为了区分typedef重新定义的结构体名称和变量名,最要在把结构体名称的首字母大写
声明一个变量的基本结构是:基本数据类型+变量名
在main函数中声明一个结构体变量应该为:
#include <studio.h>
struct Student{
char *name;
int id;
int age;
};
int main(){
struct Student stu1;
struct Student stu2;
...
return 0;
}
但是我们利用typedef可以这样:
#include <studio.h>
struct Student{
char *name;
int id;
int age;
};
int main(){
typedef struct Student Student;
Student stu1;
Student stu2;
...
return 0;
}
或者我们可以在声明结构体(这是这个结构体可以是匿名结构体)时就可以用typeof,具体如下 :
#include <studio.h>
/*typedef struct {
char *name;
int id;
int age;
}Student;
*/ //or//
typedef struct Student{
char *name;
int id;
int age;
}Student;
int main(){
Student stu1;
Student stu2;
...
return 0;
}
6.嵌套结构体
比如我想在Student结构体里插入一个结构体Birthday,Birthday为一个结构体他的数据有年月日,
#include <studio.h>
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;//新的结构体类型(名称)
typedef struct Student{
char *name;
int id;
int age;
Birthday(类型) birthday(变量);
}Student;
int main(){
Student stu1;
Student stu2;
...
return 0;
}
当然在生日这个结构体里也可以嵌套其他的结构体
3.结构体变量
1.声明结构体变量
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;//新的结构体类型(名称)typedef struct Student{
char *name;
int id;
int age;
Birthday(类型) birthday(变量);
}Student;
这两个部分是声明结构体,如果不使用的话不会占用内存,需要用结构体类型来声明变量才能分配内存空间(深红色部分就是结构体类型)
有两种声明变量的方式,一是如下图这个在main函数中定义
#include <studio.h>
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;//新的结构体类型(名称)
typedef struct Student{
char *name;
int id;
int age;
Birthday(类型) birthday(变量);
}Student;
int main(){
Student stu1,stu2;
...
return 0;
}
二是直接在声名结构体时定义
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;//新的结构体类型(名称)typedef struct Student{
char *name;
int id;
int age;
Birthday(类型) birthday(变量);
}Student, stu1,stu2;
2.给结构体变量赋值
1.简单结构体赋值
给结构体赋值时只能挨个赋值比如我要给下边这个结构体赋值
typedef struct Student{
char *name;//姓名
int id;//学号
int age;//年龄int score;//成绩
}Student, stu1;
我可以在main函数中这样写
int main()
{
stu1 = {"xiaoming",101,18,98};
}
2.嵌套结构体赋值
如果我现在要给下列的嵌套结构体赋值应该怎么改呢
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;//新的结构体类型(名称)typdef struct Student{
char *name;
int id;
int age;
Birthday(类型) birthday(变量);
}Student, stu1;
只要在括号里对应位置多加一个大括号供给结构体变量birthday赋值即可具体形式如下
int main()
{
stu1 = {"xiaoming",101,18,{2006,1,18}}
}
3.访问结构体变量
访问结构体变量需要“.”操作符且结构体的数据只能单个访问
(变量名).(数据)如 stu1.*name stu1.id
如果要访问上边的birthday的数据要连续使用"."操作符比如我要访问上边birthday的年月日,
//打印birthday年月日
#include <studio.h>
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;
typedef struct Student{
char *name;
int id;
int age;
Birthday
}Student stu1;
int main()
{
stu1 = {"xiaoming",101,18,{2006,1,18}}
printf("%d-%d-%d",stu1.birthday.year,stu1.birthday.mouth,stu1.birthday.day);
return 0;
}
4.结构体作为函数参数的使用
此时我想创造一个函数用来将结构体的数据打印出来
#include <studio.h>
void print(Student stu1)
{
printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",stu1.*name,stu1.id,stu.age,stu1.birthday.year,stu1.birthday.mouth,stu1.birthday.day);
}
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;
typedef struct Student{
char *name;
int id;
int age;
Birthday
}Student ;
int main()
{
Student stu1 = {"xiaoming",101,18,{2006,1,18}};
stu2 = {"xiaohua",102,19,{2005,1,20}};
print(stu1);
print(stu2);
return 0;
}
4.结构体指针
1. 了解结构体指针的优点
运用指针前 我们要先了解为什么要运用指针,指针有什么优点值得我们用?
在结构体给函数传参时,这个过程要完成数据的拷贝,就比如上边的打印结构体的函数,如果利用指针,我们都知道指针利用的是地址,我在只需要在主函数中将stu1与stu2的地址传给函数。函数接收到两个的地址而不是数据的拷贝,大大加快了运行效率
2.声明结构体指针
声明结构体指针方式:
声明一个指向结构体变量的指针,假设刚好有一个stu1
Student *pStu = &stu1;//指针名可以随意取
传参过程的书写形式,注意如何传参(特别是函数内访问结构体成员的变化)
3.指针访问结构体成员(单个结构体与嵌套结构体)
#include <studio.h>
typedef struct Student{
char *name;
int id;
int age;
}Student ;
void print(Student *pStu)
{
printf("姓名:%s 学号:%d 年龄:%d ",pStu->name,pStu1->id,pStu->age);
}//注意!!!!!如果要利用结构体指针则访问变量时要变换"."语句为"->"语句
int main()
{
Student stu1 = {"xiaoming",101,18};
Student *pStu = stu1;
print(pStu);
return 0;
}
指针访问单个结构体成员
void print(Student *pStu)
{
printf("姓名:%s 学号:%d 年龄:%d ",pStu->name,pStu1->id,pStu->age);
}//注意!!!!!如果要利用结构体指针则访问变量时要变换"."语句为"->"语句
注意@!!!!!! 我们可以观察到结构体成员的访问不再是(结构体变量名称).(结构体成员)的形式而是变成了(指针名称) -> (结构体成员)的形式
而且声明结构体指针的方式与声明整形字符型的指针形式一致,都是(数据类型)+(*指针名称)
函数接收参数时注意括号内要接收完整 数据类型+名称(*指针名称)或其他
关于利用指针传参时调用嵌套结构体数据的不同之处
指针访问嵌套结构体成员(!!!!!重点!!!!!)
#include <stdio.h>
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;
typedef struct Student{
char *name;
int id;
int age;
Birthday birthday;
}Student ;
void print(Student *pStu)
{
printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",pStu->name,pStu->id,pStu->age,pStu->birthday.year,pStu->birthday.mouth,pStu->birthday.day);
}
int main()
{
Student stu1 = {"xiaoming",101,18,{2006,1,18}};
Student stu2 = {"xiaohua",102,19,{2005,1,20}};
Student *pStu = &stu1;//指针指向stu1
print(pStu);
pStu = &stu2;//指针重新指向stu2
print(pStu);
return 0;
}
void print(Student *pStu)
{
printf("姓名:%s 学号:%d 年龄:%d %d-%d-%d",pStu->name,pStu->id,pStu->age,pStu->birthday.year,pStu->birthday.mouth,pStu->birthday.day);
}birthday与year mouth day之间并没有引用指针所以不会改变它们之间的调用方式
番外篇->结构体指针函数传参的实现方式,上面提到了在main函数中定义一个指针来指向结构体变量stu1,下边直接传地址的方式更加简单便捷,注意!!!只有单个结构体变量可以这样
typedef struct
{
char name[10];
int id;
}stu;
int main()
{
stu stu1;
chuancan(&stu1);
}
void chuancan(stu *p)
{
}
5.结构体占用的内存
内存对齐问题
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday,birthday;
printf("%d",sizeof(birthday));运行结果为12(int 所占字节数为4)
typedef struct Birthdy{
int year;
char mouth;
}Birthday,birthday;
printf("%d",sizeof(birthday));运行结果为8(内存对齐)
typedef struct Birthdy{
int year;
char mouth;
char a[3];
}Birthday,birthday;
printf("%d",sizeof(birthday));运行结果为8 char类型总占字节数与int类型相同不触发内存补齐
6.结构体数组
如果此时要储存多个学生的姓名成绩学号等数据,一一输入太麻烦,这时候就用到结构体数组
#include <stdio.h>
typedef struct Birthdy{
int year;
int mouth;
int day;
}Birthday;
typedef struct Student{
char *name;
int id;
int age;
Birthday birthday;
}Student ;
int main()
{
Student Students[]=//结构体数组名称
{
{"xiaoming",101,18,{2006,1,18}},
{"xiaohua",102,19,{2005,1,20}},
{"xiaohua",102,19,{2005,1,20}},
{"xiaohua",102,19,{2005,1,20}}
....
};
return 0;
}
最后的知识点设计了指针,数组,函数,结构体的混合知识较为复杂需要多看几遍进行理解