结构体_1
结构体类型
结构体的定义和声明
结构体本质上是不同的数据类型的集合,它把不同类型的数据组合为一个整体。它的优点是可以体现数据项之间的关系。
声明
struct student // struct关键字 + 结构体名字
{
int id; //学生学号 成员变量之间用分号隔开
char name[10]; //姓名
char sex; //性别
int age; //年龄
int total; //总分
}; //切记此处有分号
结构体类型的定义,类型是不会占用内存空间的,只有将每一个成员变量赋值之后才会占用对应空间
结构体的定义
有三种方法可以用来定义结构体变量:
- 先声明结构体类型再定义结构体变量
struct student maye; //maye是变量名
- 在声明结构体类型的同时定义变量
struct student
{
int id;
char name[10];
char sex;
int age;
int total;
} maye;
- typedef取别名之后再定义变量
PS: typedef定义是指将关键字和结构体类型名定义为别名
typedef struct student STU;
/*此时上述第一种定义方式也可以如下*/
STU maye;
结构体变量的初始化
在定义结构体变量的同时通过{}的方式为每一个成员变量进行赋初值。对于变量成员可以全部初始化,也可以部分初始化。
struct student maye = {520, "maye", "男", 18, 700} ;//全部初始化
struct student maye = {520, "maye", "男"}; //部分初始化,为初始化的部分为0
struct student maye = {0}; //全部初始化为0
struct student maye = {520, "maye", "男", 18, 700};
struct student zc = maye; //用另一个结构体变量初始化
和数组一样,结构体的初始化只能从左到右诸葛初始化,不能跳过。此外,在初始化的时候,顺序及类型要一一对应
结构体变量的使用
- 非指针型结构体变量的使用: 结构体变量名.成员名
- 指针型结构体变量的使用: (*结构体指针).成员名
结构体变量输入输出和嵌套
结构体变量的输入输出
使用结构体变量时,必须引用成员。
scanf("%d %s %s %d %d\n", &maye.id, &maye.name, &maye.sex, &maye.age, &maye.total);
在使用数组的时候,对数组进行定义的时候如果定义完成了就再也不能对数组进行整体赋值,但是在结构体中可以实现。
strcu student maye = {100, "maye", 1};
maye = (struct student) {111, "zc", 1, 56, 99}; //此处的强制转换类型不能省略
结构体嵌套
在一个结构体内包含另一个结构体作为其成员,有两种写法。
- 直接把结构体定义在另一个结构体内,同时定义结构体变量。
【使用:当出现结构体嵌套时,必须以级联方式访问结构体成员,即通过成员选择运算符逐级找到最底层的成员时再引用】
struct student
{
int id;
char name[10];
char sex;
int age;
int total;
struct birthday
{
int day;
int month;
int year;
}birth;
} maye;
//然后我们对生日进行赋值
maye.birth.year = 2000;
maye.birth.month = 12;
maye.birth.day = 29;
//然后进行输出
printf("%d %d %d",maye.birth.year, maye.birth.month, maye.birth.day);
- 在此结构体之前定义好结构体类型,然后在里面定义结构体变量。
struct student
{
int id;
char name[10];
char sex;
int age;
int total;
struct birthday birth;
} maye;
struct birthday
{
int day;
int month;
int year;
}birth;
结构体数组和指针
结构体数组
结构体中也有数组,称为结构体数组。它与前面讲的数值型数组几乎是一模一样的,只不过需要注意的是,结构体数组的每一个元素都是一个结构体类型的变量,都包含结构体中所有的成员项。
定义:结构体类型 数组名[SIZE];
struct student VIP7[70] = {{111, "zc", 1, 56, 99}, ……};
- 这就定义了一个结构体数组,共有 70 个元素,每个元素都是一个结构体变量,都包含所有的结构体成员。
- 初始化方式和数值型数组是一样的。
- 使用时一定不要忘记加[SIZE]。
结构体指针
前面我们通过“结构体变量名.成员名”的方式引用结构体变量中的成员,除了这种方法之外还可以使用指针。
定义指针:结构体类型 *指针名;
假设设定一个结构体:
struct student
{
int boy;
int girl;
}stu;
struct student *pyme = &stu;
stu.boy = 100;
stu.girl = 200;
printf("%d %d", pyme->boy, pyme->girl);
printf("%d %d", stu.boy, stu.girl);
注意:指针一定要有指向,不能出现野指针,也不能对空指针进行操作!
针对结构体数组,假设我们定义一个结构体数组
struct student
{
int boy;
int girl;
}stu;
stu[70] = {{1,2}, {3,4}……}
//如果我们想逐个输出每一个结构体里面的内容
for(int i = 0; i <= 70; i++)
{
printf("%d %d \n", stu[i].boy, stu[i].girl);
printf("%d %d \n", (stu + i)->boy, (stu + i)->girl);
/*两种表达方式均可*/
}
结构体变量所占内存大小
- 用sizeof运算符可以获得结构体的大小。
- 结构体类型所占内存字节数不是各成员占内存的总和。
** 内存对齐(字节对齐):**
- 为了更快的存取数据
- 字节对齐与定义的结构体类型有关
- 不同的系统和编译器,内存对齐方式可能也不一样
对齐规则:
- 一般情况下默认4字节对齐
- 结构体的总大小为结构体最宽基本类型成员大小的整数倍
- 在对齐时,编译器会自动加上填充字节
- 结构体总大小是包括填充字节
例:
struct student
{
int a;
char cc;
int b;
};
struct abc
{
double b;
char c[3];
};
针对上述两个结构体,第一个结构体student中,虽然char类型数据占1个字节,但是按照我们最大对齐的原则,它也占四个字节,所以总大小为12个字节。
同理,在第二个结构体当中,字符串数组并不是基本数据类型,所以这里最大的基本数据类型师double,占8个字节,所以这个结构体整体占16个字节。