为什么要使用结构体
C语言提供给了我们很多数据类型,int ,char,float,double等,但是这些并不能满足我们的需要。比如我们要存储学生的信息(姓名,年龄,学号等),当然我们可以把它们一个一个的存储,但是这样太零散了,为了使得学生信息成为一个整体,我们要自己创建一个类型——结构体。
如何声明结构体类型
struct关键字——建立结构体声明
struct stu{
int age;
float score;
char name;
};
在这里struct表面后面的是一个结构体,stu是结构体标记,可写可不写
写的话,之后使用该结构体的时候,可以直接建立变量(一个结构可以创建多个结构变量);这里的struct stu可以理解为int,char,后面的liming,lihua才是变量
struct stu liming;
struct stu lihua;
不写的话,该结构只能在声明的时候使用一次(这里表示为该结构建立了stu1,stu2两个变量 )
struct {
int age;
float score;
char name;
}stu1,stu2;
typedef关键字——为类型去一个别名
typedef struct stu{
int age;
float score;
char name;
}stu;
typedef int u16;
第一个程序意思是之后可以使用stu代表struct stu;
第二个程序意思是之后可以使用u16代表int;
那么之后为结构体定义变量可以这样写stu liming;等价于struct stu liming;
注意typedef只可以为类型取别名。
结构体嵌套
比如学生信息的生日包含年月日;一个结构体内可以嵌套另一个结构体;如第二段程序。访问的时候参照第三段程序
typedef struct birthday{
int year;
int mon;
int day;
}Birthday;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
Stu liming;
//如何访问
liming.birthday.year;
结构体变量
声明结构体变量
注意:在只是声明结构体的时候,她并不占据内存空间,如int本身并不占据空间,只有声明变量之后才占据内存空间。
方法如下;Stu此时可以看作int等类比int 即可;如int a,b,c;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
Stu liming;
结构体变量赋值
typedef struct birthday{
int year;
int mon;
int day;
}Birthday;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
Stu liming = {11,99,'H',{2000,11,12}};
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART3_Init (9600);
printf("age is %d/r/n,score is %1f/r/n,name is %c/r/n,birthday is %d.%d.%d/r/n",
liming.age,liming.score,liming.name,liming .birthday.year,liming .birthday.mon,liming .birthday.day);
while(1)
{
}
}
结果
访问结构体变量成员
使用.操作
printf("age is %d/r/n,score is %1f/r/n,name is %c/r/n,birthday is %d.%d.%d/r/n",
liming.age,liming.score,liming.name,liming .birthday.year,liming .birthday.mon,liming .birthday.day);
结构体作为函数参数
程序
typedef struct birthday{
int year;
int mon;
int day;
}Birthday;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
void PrintfStu(Stu stu)//相当于void printfstu(int a)
{
printf("age is %d/r/n,score is %1f/r/n,name is %c/r/n,birthday is %d.%d.%d/r/n",
stu.age,stu.score,stu.name,stu .birthday.year,stu .birthday.mon,stu .birthday.day);
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
Stu liming = {11,99,'H',{2000,11,12}};
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART3_Init (9600);
PrintfStu(liming);
while(1)
{
}
}
结果
上述没有错误,但是执行效率相对较低。参数传递的过程中需要先把参数复制之后在传递,较慢。
如果在函数当中传递的是指针,直接传递结构体地址,速度就快了
结构体指针
程序如下:
typedef struct birthday{
int year;
int mon;
int day;
}Birthday;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
void PrintfStu(Stu* p)
{
printf("age is %d/r/n,score is %1f/r/n,name is %c/r/n,birthday is %d.%d.%d/r/n",
p->age,p->score,p->name,p->birthday.year,p->birthday.mon,p->birthday.day);
}//结构体指针访问结构体成员->
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
Stu liming = {11,99,'H',{2000,11,12}};
Stu* p ; //声明结构体指针
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART3_Init (9600);
p = &liming; //相当于结构体指针赋值
PrintfStu(p);
while(1)
{
}
}
结果:
结构体数组
如果1001个学生,我们要用结构体定义100个变量吗?不,用结构体数组可以解决
程序:
typedef struct birthday{
int year;
int mon;
int day;
}Birthday;
typedef struct stu{
int age;
float score;
char name;
Birthday birthday;
}Stu;
void PrintfStu(Stu stu)
{
printf("age is %d/r/n,score is %1f/r/n,name is %c/r/n,birthday is %d.%d.%d/r/n",
stu.age,stu.score,stu.name,stu .birthday.year,stu .birthday.mon,stu .birthday.day);
}
/*******************************************************************************
* 函 数 名 : main
* 函数功能 : 主函数
* 输 入 : 无
* 输 出 : 无
*******************************************************************************/
int main()
{
Stu stu[] ={
{11,99,'H',{2000,11,12}},
{10,80,'L',{2001,10,30}}
};
SysTick_Init(72);
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
USART3_Init (9600);
PrintfStu(stu[1]);
while(1)
{
}
}
结果:
结构体内存大小
结构体内存大小就是把结构体里面的每个参数大小加一起,但是要注意内存对齐
内存对齐
是为了硬件访问数据更快才有的
硬件用奇数地址访问一个字节的速度快,但是用一个奇数地址访问4个字节的速度慢;
用偶数地址访问的速度快,无论几个字节。