目录
一:什么是结构体
结构体的定义:把不同类型的数据结合在一起,形成集合
结构体访问属性,使用点运算符
结构体,示例如下:
#include<stdio.h>
//描述一个学生 学号 姓名 年龄 密码
struct student_t{
int sno; //学号 数据成员又名属性,用分号隔开
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}; //分号不能少
int main()
{
//结构体定义
struct student_t stu={1001,"lily","123456",18};
//结构体信息访问 用.点运算符 结构体名.属性名
printf("stu:hello,%d %s %d\n",stu.sno,stu.name,stu.age);//stu:hello,1001 lily 18
return 0;
}
若是 只定义不初始化,没有被赋值到的属性都会是随机值,因此是不提倡这样定义的:
struct student_t stu1;
二:结构体 逐个赋值属性
结构体定义[属性赋值]【一个一个地去 赋值属性】,示例如下:
#include<stdio.h>
#include<string.h>//strcpy
//描述一个学生 学号 姓名 年龄 密码
struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
};
int main()
{
//结构体定义
struct student_t stu1; //只定义没有初始化
stu1.sno=1002; //没有初始化只能一个一个赋值
strcpy(stu1.name,"kity");//字符数组的赋值,需要注意strcpy引头文件
stu1.age=20;
printf("stu1:hello,%d %s %d\n",stu1.sno,stu1.name,stu1.age);//stu1:hello,1002 kity 20
return 0;
}
三:结构体 定义时部分初始化
结构体在定义的时候部分初始化,没有被初始化的属性是 0/空字符串,示例如下:
#include<stdio.h>
#include<string.h>
struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
};
int main()
{
//结构体定义
struct student_t stu2={1003}; //部分初始化 其他位置自动补零 字符串是空字符串
printf("stu2:hello,%d %s %d\n",stu2.sno,stu2.name,stu2.age);//stu2:hello,1003 (空字符串) 0
return 0;
}
结构体各个属性存储的地址是连续的
结构体的定义[主要有三种]:
定义并全部初始化
只定义不初始化
定义部分初始化
四:结构体的内存占用
使用 sizeof()函数 用来计算字节长度
1.计算内存,以最大的存储类型 【内存对齐】
示例一:
#include<stdio.h>
#include<string.h>
struct student_t{
int sno; //学号 4
char name[20]; //姓名 4*5
char pwd[18]; //密码 补充2个 4*5
int age; //年龄 4 共4+20+20+4=48
};
//计算内存 以最大的存储类型内存对齐
int main()
{
struct student_t stu={1001,"lily","123456",18};
printf("stu size=%d\n",sizeof(stu));//stu size=48
return 0;
}
示例二:
#include<stdio.h>
#include<string.h>
struct student_t{
int num1; //4
char ch; //1补3 为4
int num2; //4 总4+4+4=12
};
//计算内存 以最大的存储类型内存对齐
int main()
{
struct student_t stu={4,"lily",18};
printf("stu size=%d\n",sizeof(stu));//stu size=12
return 0;
}
2.相邻的同类型的可以合并,数据类型越小的一起往前面放可以节省内存空间
同样的数据类型,不同的排列顺序,内存的占用也不同【学习 内存空间的节省】
数据类型小的char,统一放置于前面
#include<stdio.h>
#include<string.h>
struct student_t{
char num1; //1
char num2; //1 1 1合并为2 补6为8 最后是8
double num3; //8 总8+8=16
};
//相邻的同类型的可以合并的 数据类型越小的一起前面放可以节省空间
int main()
{
struct student_t stu={"kity","lily",18.123};
printf("stu size=%d\n",sizeof(stu));//stu size=16
return 0;
}
像以下这种,没有把数据类型小的,统一放置在前面,就相对地浪费内存占用
#include<stdio.h>
#include<string.h>
struct student_t{
char num1; // 1 补7 为8
double num2; // 8
char num3; // 1 补7 为8 总8+8+8=24
};
//相邻的同类型的可以合并的 数据类型越小的一起前面放可以节省空间
int main()
{
struct student_t stu={"kity",18.123,"lily"};
printf("stu size=%d\n",sizeof(stu));//stu size=24
return 0;
}
3.结构体内存占用的计算练习
练习一:
#include<stdio.h>
#include<string.h>
struct student_t{
int NO[4]; // 4 向4看齐 4*4=16
char Name[20]; // 1 向4看齐 4*5=20 总16+20=36
};
int main()
{
struct student_t stu={18,"kity"};
printf("stu size=%d\n",sizeof(stu));//stu size=36
return 0;
}
练习二:
#include<stdio.h>
#include<string.h>
struct student_t{
int NO[4]; // 4 向8看齐 4*4=》 16=》 8*2 16
double str[4]; // 8 向8看齐 8*4=》 8*4 32 总16+32=48
};
int main()
{
struct student_t stu={18,18.123};
printf("stu size=%d\n",sizeof(stu));//stu size=48
return 0;
}
五:typedef 重命名数据类型
typedef:作用是 能够实现 结构体数据类型的简写,使用示例如下:
#include<stdio.h>
//重命名数据类型 struct student_t改名为STU_T
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
int main()
{
//结构体定义
STU_T stu={1001,"lily","123456",18};
//结构体信息访问 用.点运算符 结构体名.属性名
printf("stu:hello,%d %s %d\n",stu.sno,stu.name,stu.age);//stu:hello,1001 lily 18
return 0;
}
六:结构体的定义
结构体的定义 [3种赋值方法]
1.定义 直接赋值
2.定义 属性赋值 [逐个赋值属性]
3.内存赋值 memcpy
具体示例如下:
1.直接赋值
#include<stdio.h>
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
int main()
{
//结构体定义
STU_T stu={1001,"lily","123456",18};//全部初始化
STU_T stu1; //只定义 没初始化
stu1=stu;//直接赋值 结构体是一种数据类型
//结构体信息访问 用.点运算符 结构体名.属性名
printf("stu:hello,%d %s %d\n",stu.sno,stu.name,stu.age);//stu:hello,1001 lily 18
printf("stu1:hello,%d %s %d\n",stu1.sno,stu1.name,stu1.age);//stu1:hello,1001 lily 18
return 0;
}
2.属性赋值 示例在文章的第二标题
3.内存赋值memcpy
#include<stdio.h>
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
int main()
{
//结构体定义
STU_T stu={1001,"lily","123456",18};//全部初始化
STU_T stu2={1003}; //部分初始化
//内存赋值法 stu2获取stu的数据
memcpy(&stu2,&stu,sizeof(STU_T));//后面的赋值给前面
printf("stu2:hello,%d %s %d\n",stu2.sno,stu2.name,stu2.age);//stu2:hello,1001 lily 18
return 0;
}
七:结构体数组
结构体数组的使用,示例:
#include<stdio.h>
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
int main()
{
int i=0;
//结构体数组 部分初始化 int 补0 字符 补空字符串
//数据类型 结构体名[长度]={{},{},{}};
STU_T stuArr[38]={
{1001,"lily","123456",18},
{1002,"kity","123123",19},
{1003,"tom","123489",20}
};
//循环访问结构体数组中每一个成员的信息
for(i=0;i<3;i++)
{
printf("stu:hello,%d %s %d\n",stuArr[i].sno,stuArr[i].name,stuArr[i].age);
//stu:hello,1001 lily 18
//stu:hello,1002 kity 19
//stu:hello,1003 tom 20
}
return 0;
}
八:结构体作为函数参数
#include<stdio.h>
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
void printStuInfo(STU_T stu);
int main()
{
int i=0;
STU_T stuArr[38]={
{1001,"lily","123456",18},
{1002,"kity","123123",19},
{1003,"tom","123489",20}
};
for(i=0;i<3;i++)
{
printStuInfo(stuArr[i]);
//stu:hello,1001 lily 18
//stu:hello,1002 kity 19
//stu:hello,1003 tom 20
}
return 0;
}
//打印一个学生结构体信息
//结构体作为参数传递 int char float double 按值传递
//改变函数内部值 外部不会变化 要想变化 引用 指针 寻找地址改变其值
void printStuInfo(STU_T stu)
{
printf("stu:hello,%d %s %d\n",stu.sno,stu.name,stu.age);
}
九:结构体作为函数返回
#include<stdio.h>
typedef struct student_t{
int sno; //学号
char name[20]; //姓名
char pwd[18]; //密码
int age; //年龄
}STU_T;
STU_T editStuInfo(STU_T stu);
int main()
{
int i=0;
STU_T stu={1001,"lily","123456",18};//全部初始化
STU_T stu1;//只定义没初始化
//结构体数组
STU_T stuArr[38]={ //38个学生 部分初始化
{1001,"lily","123456",18},
{1002,"kity","123123",19},
{1003,"tom","123489",20}
};
stu1 = editStuInfo(stuArr[0]); //改变第一个学生(学号)
printf("stu:hello,%d %s %d\n",stu.sno,stu.name,stu.age);//stu:hello,1001 lily 18
printf("stu1:hello,%d %s %d\n",stu1.sno,stu1.name,stu1.age);//stu1:hello,10086 lily 18
return 0;
}
//函数内部改变 外部也变 结构体可以作为返回值
STU_T editStuInfo(STU_T stu)//改变学生学号
{
stu.sno=10086;
return stu; //结构体既可以作为参数 又可以作为返回值
}