目录
一、结构体类型定义
二、结构体变量的定义
①先定义结构体类型,再定义结构体变量
②在定义结构体类型的同时,定义结构体变量
③直接定义结构体变量
三、结构体变量的内存分配
四、结构体变量的初始化
五、结构体变量的引用
一、结构体类型定义
结构体是一种构造数据类型,可以把不同类型的数据整合在一起,每一个数据都称为该结构体类型的成员。使用结构体时,首先需要对结构体类型进行定义,结构体类型的定义如下所示:
struct 结构体类型名称
{
数据类型 成员名1;
数据类型 成员名2;
。。。
};
//"struct"是定义结构体类型的关键字
实例演示:
学生信息包括:学号(num)、姓名(name)、性别(sex)、年龄(age)、地址(address),将其定义为一个名为Student的结构体。
struct Student{int num[10];char name[10];char sex;int age;char address[30];};
【注意】结构体类型中的成员,也可以是一个结构体变量。
实例分析:
struct Date{int year;int month;int day;};struct Student{int num[10];char name[10];char sex;struct Date birthday;//出生日期birthday为结构体类型Date}stu1;
此时结构体类型Student的类型结构如下:
【注释】
结构体类型定义以“struct”开头,后面跟的是结构体类型的名称,该名称的命名规则与变量一致定义好一个结构体类型后,并不意味着立即分配一块内存单元存放各个数据成员,它只是告诉编译器,该结构体类型由哪些数据类型的成员构成,各占多少个字节,按什么格式存储,并把它们当作一个整体来处理。结构体类型定义的末尾括号的分号必不可少。结构体类型的成员可以是一个变量,但不能是自身结构体类型的变量。
二、结构体变量的定义
定义了结构体类型,系统不会为它分配内存空间。为了能在程序中使用结构体类型的数据,应该定义结构体类型的变量,并在其中存放具体的数据。定义结构体变量的方法主要有下面三种:
①先定义结构体类型,再定义结构体变量
struct Student{int num[10];char name[10];char sex;int age;char address[30];};struct Student stu1,stu2;//stu1、stu2为结构体类型变量,各自可以存储一组基本类型的变量,且分别占据一块连续的内存空间
②在定义结构体类型的同时,定义结构体变量
struct Student{int num[10];char name[10];char sex;int age;char address[30];}stu1,stu2;//变量stu1和stu2的数据类型都是结构体类型Student
③直接定义结构体变量
struct {int num[10];char name[10];char sex;int age;char address[30];}stu1,stu2;//stu1、stu2为结构体变量,但定义的结构体没有类型名称(又称“匿名结构体”)
【注意】结构体类型是用户自定义的一种数据结构,它同简单数据类型一样,在编译时对结构体类型不分配空间。只有在用它定义某个变量时,才会为该结构体变量分配结构体类型所需大小的内存单元。
三、结构体变量的内存分配
结构体变量一旦定义,系统就会为它分配内存空间。结构体变量占据的内存大小是按字节对齐机制来分配的。
字节对齐:字节按照一定规则在空间上排列。字节对齐遵循两条规则:
①结构体的每个成员变量相对于结构体首地址的偏移量,是该成员变量的基本数据类型(不包括结构体、数组等)大小的整数倍;如果不够,编译器会在成员之间加上填充字节。
实例分析:
struct{char a;double b;int c;short d;}S;
结构体变量S中各个成员在内存中分布情况如下:
为什么有7个字节的填充字节?
成员变量a的地址为结构体变量S的首地址,占1字节;成员变量b占8个字节,但是如果字节跟着变量a后面,就违背了字节对齐原则①,所以至少需要在前面填充7个字节,使得变量的地址相对于首地址是整数倍。变量c,d相对于首地址的偏移量分别是16,20字节正好是4和2的倍数。
②结构体的总大小为结构体最长的结构体成员变量大小的整数倍,如果不够,编译器会在最末尾一个成员之后加上填充字节
根据原则①计算出上述的结构体变量S所占的内存大小为22字节,但这个不符合字节对齐的原则②,不是8的倍数,因此编译器会在最后填充两个字节,使之成为24字节。
#include <stdio.h>struct{char a;double b;int c;short d;}S;int main() {printf("结构体变量S占字节大小为:%d\n", sizeof(S));}
运行结果:
四、结构体变量的初始化
结构体变量中存储的是一组类型不同的数据,因此,为结构体变量初始化的过程,实际就是为结构体个成员初始化的过程。
结构体变量初始化的方式有下面两种:
①在定义结构体类型和结构体变量的同时,对结构体变量进行初始化
struct Student{int num;char name[10];char sex;int age;}stu={1001,"Li Lei",'M',18};//结构体变量stu定义的同时进行了初始化
②先定义结构体类型,再在定义结构体变量的同时进行初始化
struct Student{int num;char name[10];char sex;int age;};struct Student stu={1001,"Li Lei",'M',18};
【注意】在对结构体初始化时,如果只初始化其中一部分成员,只需要对前面的成员初始化,后面的成员可以空余,因为给成员变量赋值时,编译器是按成员从前往后匹配,而不是按数据类型自动匹配
五、结构体变量的引用
定义并初始化结构变量的目的是使用结构体变量的成员。结构体变量的引用方式如下:
结构体变量名.成员名
#include <stdio.h>struct Student{int num;char name[10];char sex;int age;};struct Student stu = { 1001,"Li Lei",'M',18 };int main() {printf("学生信息:\n");printf("学号:%d\n", stu.num);printf("姓名:%s\n", stu.name);printf("性别:%c\n", stu.sex);printf("年龄:%d\n", stu.age);}
运行结果: