结构体学习笔记(c语言)
为什么要使用结构体
c语言中本身有int,float,double等等等等基本数据类型,但当我们要区处理一些比较复杂的数据的时候,这点基本数据类型就不太够用了。
而c语言中的结构体可以对数据的一些基本信息进行分装,假如说处理一个班级的的成绩,结构体同时处理学号,姓名,分数,班级等等多类别的信息就方便很多。
如何声明结构体类型
struct关键词
#include<stdio.h>
struct Name{};
//结构体名字最好首字母大写以便与变量区分开
//结构体的声明后接一个{}来方便对数据进行分装,在{}的末尾加;表示结束
int main(){
}
结构体成员
#include<stdio.h>
struct Student{
int id;//学号
char name[100];//用一个字符数组装学生的名字
//也可以用一个字符指针char*name;
int age;//年龄
float score;//成绩
//……还可以添加更多的属性
};
//可以将结构体理解为抽象数据类型,是由我们定义和构造的,由很多的基本数据类型组成。
//结构体名字实际上是该抽象数据类型名称,是类型名称而非变量名。
空结构体
#include<stdio.h>
struct EmptyStruct{};
//这个结构体里面什么属性也没有;又或者是说这些属性是要我们后面去填写的
像这样的结构体我们称之为空结构体
匿名结构体
匿名结构体的意思是这个结构体它可以没有名字
#include<stdio.h>
struct {
int id;
char name[100];
int age;
float score;
};
//我们将结构体名字删去就得到了匿名结构体
//一般匿名结构体用于该结构体被使用的次数很少的情况,如果要使用该结构体,则需在结构体的}后加上会使用到该结构体的变量名#include<stdio.h>
struct {
int id;
char name[100];
int age;
float score;
}stu1,stu2;
这样就定义了两个学生的系列信息,注意stu1和stu2是变量而非类型
使用typedef
type表示类型,def表示定义,可以用typedef去定义一个新的数据类型。不然的话我们在后面每次使用typedef都会要用struct关键词,而经过了typedef定义的可直接使用名称进行结构体的调用。
#include<stdio.h>
struct Student{
int id;
char name[100];
int age;
float score;
};
typedef struct Student Student1;相当于在后面的代码中可以直接用Student1代替Student。
typedef相当于专门给一个类型取名的。
在声明结构体的时候可以进行类型重命名:
#include<stdio.h>
typedef struct Student{ //若以这种方式定义,则结构体名称可不保留
int id;
char name[100];
int age;
float score;
} Student1;
一般来说用typedef声明结构体会更加方便。
结构体的嵌套定义
#include<stdio.h>
typedef struct Birthday {
int year;
int month;
int day;
}Birthday;
typedef struct Student{
int id;
char name[100];
int age;
float score;
Birthday Birthday;//结构体的嵌套
} Student1;当访问的时候则要多层去访问:
stu.Birthday.year;
结构体变量
声明结构体变量
当我们只是声明了某个结构体类型而没有定义该类型的变量的时候,它(类型)是不占用内存的,占用内存的是变量。
int main(){
Student stu1,stu2;
return 0;
}
这样就有的两个变量了,之后我们怎么对int,float等等类型变量干了什么就可以干什么了。
结构体变量的赋值
根据对应的声明的结构体输入对应的数值即可。
#include<stdio.h>
typedef struct Birthday {
int year;
int month;
int day;
}Birthday;
typedef struct Student{
int id;
char name[100];
int age;
float score;
Birthday Birthday;>} Student1;
int main(){
Student stu1={108,“李华”,14,98,{2008,9,28}};
//这里Student是数据类型,stu1是变量名。
return 0;
}
这样就完成了对结构体变量的赋值。嵌套也不用管,当一个整体来看即可。
访问成员结构体成员
访问成员变量要使用.操作符。
int main(){
Student stu1={108,“李华”,14,98,{2008,9,28}};
printf(“学号:%d\t姓名:%s\t年龄:%d\t成绩:%.2f\t生日:%d-%d-%d\n”,
stu1.id,stu1.name,stu1.age,stu1.score,
stu1.Birthday.year,stu1.Birthday.month,stu1.Birthday.day);
return 0;
}
结构体作为函数参数
void print(Student stu){
printf(“学号:%d\t姓名:%s\t年龄:%d\t成绩:%.2f\t生日:%d-%d-%d\n”,
stu.id,stu.name,stu.age,stu.score,
stu.Birthday.year,stu.Birthday.month,stu.Birthday.day);
}
int main(){
Student stu1={108,“李华”,14,98,{2008,9,28}};
printf(stu1);
}
结构体指针
结构体指针存在的原因:结构体内部数据可以很复杂,结构体作函数参数的时候每次完全拷贝一份过去会变得很累赘(传值),所以使用指针会更便利(传址)。
声明结构体指针,结构体指针访问结构体成员,结构体指针作为函数参数
void print(Student *pstu){//结构体指针作函数参数
printf(“学号:%d\t姓名:%s\t年龄:%d\t成绩:%.2f\t生日:%d-%d-%d\n”,
stu->id,stu->name,stu->age,stu->score,
stu->Birthday.year,stu->Birthday.month,
stu->Birthday.day);//在c语言结构体指针中不能用.访问成员变量,得用->
//但在嵌套的结构体中,下一层访问成员变量得用.因为在下一层关系中不是结构体指针
}
int main(){
Student stu1={108,“李华”,14,98,{2008,9,28}};
Student *pstu=&stu1;//声明结构体指针
print(pstu);
}
结构体数组
Student students[]={{108,“李华”,14,98,{2008,9,28}},{109,“张明”,13,96,{2009,8,20}};
//结构体数组的声明
接下来就和普通数组没差,只不过换了个数据类型而已。
结构体的内存计算
计算方式
可以用sizeof去计算,因为结构体是数据类型,所以直接把声明的数据类型名即结构体名丢进sizeof()即可得出结果
printf(“%d\n”,sizeof(Birthday));//12
//计算结构体所占内存时一般把它里面用到的数据类型对应所需内存大小加起来即可。
内存对齐
printf(“%d\n”,sizeof(Student));//40
这个嵌套的结构体内存显然和我们前面说的不一样,这涉及到内存对齐的问题。