一.简单介绍
1.为什么需要结构体:
用于表示一些基本类型数据无法表示的复杂事物
该事物的不同特征需要不同类型的基本类型数据来描述
需要通过结构体把这些特征放到1个变量里,从而形成关联
2.什么是结构体:
把一些基本数据类型组合在一起形成的1种复合数据类型
可以说,结构体是一系列自定义数据类型的统称
这些自定义数据类型都是通过基本数据类型组合而来
二.定义结构体
1.方法1(推荐):
"结构体声明"(Structure Declaration):这里没有定义1个变量,而是定义了1个数据类型(叫<struct_name>)
//有时也称为"模板",因为其描述了结构体如何存储数据
struct <struct_name> {
<type1> <name1>;
<type2> <name2>;
...
};//注意:最后有1个分号(;)
//参数说明:
type_name:该结构体的名称
type,name:包含的元素的数据类型与对应的变量名
结构体变量声明:这里才定义了1个变量
struct <struct_name> <var>[={<val1>,<val2>...}];
//这是struct <struct_name> {<type1> <name1>;...} <var>的简写
//定义和赋值也可以分开进行:<var>={<val1>,<val2>...};
//也可以定义指向该结构体变量的指针:struct <struct_name> * <var>';
//注意:ANSI C之前不能用自动变量初始化结构
//参数说明:
struct_name:结构体的名称
var:变量名
//其中包含name1,name2...等元素
val:var中包含的元素的值
//val1对应name1,val2对应name2...以此类推
//实例:
#include <stdio.h>
struct Student {//定义了1个结构体(1个数据类型)
int age;
float score;
char gender;
char reach[3];
};
int main(void) {
struct Student s1={//定义了1个结构体变量并初始化
18,78.5,'M',{'a','b','c'}
};
return 0;
}
2.方法2:
//直接定义1个结构体变量:
//缺点:想再定义1个使用本结构体的结构体变量,就需要重新定义该结构体
struct <struct_name> {
<type1> <name1>;
<type2> <name2>;
...
} <var>[={<val1>,<val2>...}];
//定义和赋值也可以分开进行(同方法1)
//参数说明:同方法1
//实例:
struct Student {
int age;
float score;
char gender;
} st2;//此处不能直接赋值
3.方法3:
//如果直接定义1个结构体变量,就可以省略结构体的名称:
struct {
<type1> <name1>;
<type2> <name2>;
...
} <var>[={<val1>,<val2>...}];
//定义和赋值也可以分开进行(同方法1)
//参数说明:同方法1
//实例:
struct {
int age;
float score;
char gender;
} st3;
三.使用结构体
1.赋值:
①在定义的同时赋值(即初始化)会给整个结构体变量赋初值:
struct <struct_name> <var>={<val1>,<val2>...};
②定义完之后,只能给结构体变量中的某元素(name1,name2...)赋值:
var.<name>=<val>;
//实例:
#include <stdio.h>
struct Student {
int age;
float score;
char gender;
};
int main(void) {
struct Student s1={18,78.5,'M'};//正确
struct Student s2;
//s2={12,78.5,'F'};//报错:[Error] expected expression before '{' token
s2.age=22;
s2.score=84.8;
s2.gender='F';//正确
printf("s1:%d,%f,%c\n",s1.age,s1.score,s1.gender);//结果:s1:18,78.500000,M
printf("s2:%d,%f,%c\n",s2.age,s2.score,s2.gender);//结果:s2:22,84.800003,F
return 0;
}
2.调用结构体变量中的元素
(1)方法1:
<struct_name>.<name>
//这里的.称为"结构体成员运算符";该运算符的优先级高于取地址符
//参数说明:
struct_name:结构体变量的名称
name:结构体变量中元素的变量名
//实例:见 三.1 部分的实例
(2)方法2(更常用):
<struct_advar>-><name>
//在计算机内部会被转换成(*<struct_advar>).<name>
//参数说明:
struct_advar:结构体指针变量
//即:用于存储结构体变量的地址的指针变量
//也可以变成(&<struct_name>)-><name>,二者相同(注意:必需加括号)
name:结构体变量中元素的变量名
//实例:
#include <stdio.h>
struct Student {
int age;
float score;
char gender;
};
int main(void) {
struct Student s1={18,78.5,'M'};//正确
struct Student* ps1=&s1;//创建1个用于存储结构体变量的地址的指针变量并赋值
//struct Student*类型的指针变量只能存储struct Student类型变量的地址
ps1->age=88;
printf("%d\n",ps1->age);//结果:88
printf("%d\n",(*ps1).age);//结果:88
printf("%d\n",(&s1)->age);//结果:88//注意:&s1必需用括号包起来
return 0;
}
3.将结构体作为参数传入函数:
//传入指针,可以修改/输出,但可能误修改,因此不够安全
//传入变量值,只能输出,但不会误修改
//但指针资源消耗小/执行速度快,因此还是推荐使用结构体指针变量
#include <stdio.h>
struct Student {
int age;
float score;
char gender;
};
void InputStudent(struct Student* st) {
//由于需要修改,形参不能是struct Student st
st->age=10;
st->score=99;
st->gender='M';
}
void OutputStudent(struct Student* st) {
//由于不需要修改,只需要输出,形参也可以是struct Student st
//但指针永远只占用8B,普通变量占用9B(如果涉及更多元素,会更多)
printf("%d,%f,%c\n",(*st).age,(*st).score,(*st).gender);
//结果:10,99.000000,M
}
int main(void) {
struct Student s1;
InputStudent(&s1);
OutputStudent(&s1);
return 0;
}
4.结构体变量的运算:
结构体变量不能相加/减/乘/除,但可以相互赋值
//实例:
struct Student {
int age;
float score;
char gender;
};
int main(void) {
struct Student s1,s2;
s1.age=33;
s1.score=87.5;
s1.gender='M';
s2=s1;
printf("%d\n",s1.age);//结果:33
return 0;
}