【1】结构体
1.概念:
由用户自定义的一种构造类型,用于描述一个复杂事物,表示多种不同类型数据的集合。
2.定义格式:
struct 结构体名
{
数据类型 成员1;
数据类型 成员2;
…
数据类型 成员n;
};
3.结构体类型大小
1)字节对齐原则
选取结构体成员中最大的类型跟value(4字节)比较,按字节数小的为标准开辟空间。
2)节省空间原则
在保证数据不被破坏的前提下,尽可能向上压缩空间。
3)特殊情况:
四字节内部对齐原则
struct num
{
char a;
short b; //4
char c; //4
int d; //4
};
sizeof(struct num) = 12
【2】结构体变量
1.概念:
通过结构体类型定义的变量称为结构体变量。
2.定义方式:
[存储类型] [结构体类型] 变量名;
1)先定义结构体,再通过结构体类型定义结构体变量。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
};
struct phone ph1;
2)定义结构体的同时定义结构体变量。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph2,ph3;
3)缺省结构体类型名定义结构体变量。
struct
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph1,ph2,ph3;
//注: 1.缺省结构体名定义变量时,只能在定义结构体的同时将所需变量定义好,
后续无法再通过struct 结构体名去定义结构体变量了。
2.一般用于结构体嵌套时,通常省略内层的结构体名。
3.结构体变量初始化
1)先定义结构体,再通过结构体类型定义结构体变量,定义变量的同时进行初始化。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
};
struct phone ph1 = {1001,“华为”,“P50 Pocket”,“骁龙888 4G”,10988};
2)定义结构体的同时定义结构体变量,同时对结构体变量进行初始化。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph2,ph3;
3)定义结构体变量时未初始化,后面再逐个成员赋值。
通过结构体变量名访问成员的形式:
通过 . 进行访问 : 结构体变量名.成员
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph3;
ph3.id = 1003;
strcpy(ph3.brand,"Apple");
strcpy(ph3.mod,"iPhone13 pro max");
strcpy(ph3.cpu,"A15");
ph3.price = 998;
4.给结构体类型起别名
typedef 原类型名 自定义名;
typedef struct
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}PH;
PH ph1;
typedef struct
{
char name[5];
int id;
struct
{
float Chinese;
float Math;
float English;
}s;
}STU;
STU student_1;
strcpy(student_1.name,"陈剑");
student_1.id = 2003101;
student_1.s.Chinese = 60.5;
作业1:计算结构体大小(文档)
作业2:预习结构体数组。
从终端录入手机信息,写一个函数,该函数参数是结构体数组,
按照手机价格从低到高顺序输出手机信息。
【3】结构体数组
1.概念:
用于存放结构体变量的数组,结构体数组中存放的元素都是结构体类型的。
2.定义方式:
1)先定义结构体类型,再通过结构体类型定义结构体数组。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
};
struct phone ph_arr2[5];
2)定义结构体的同时定义结构体数组。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph_arr[5];
3.结构体数组初始化
1)先定义结构体类型,再通过结构体类型定义结构体数组,同时对结构体数组进行初始化。
struct phone ph_arr2[5] = {{1001,“华为”,“P50”,“骁龙888”,10499},{1001,“华为”,“P50”,“骁龙888”,10499}};
2)定义结构体的同时定义结构体数组,同时对结构体数组进行初始化。
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph_arr[5] = {
{1001,"华为","P50","骁龙888",10499},
{1001,"华为","P50","骁龙888",10499}
};
3)定5义结构体数组时未初始化,之后再对数组中的元素成员分别赋值。
ph_arr[0].id = 1002;
strcpy(ph_arr[0].brand,"小米");
4.结构体数组的输入输出
struct phone ph_arr[5] = {0};
scanf("%d",&ph_arr[0].id);
通过循环进行优化:
for(int i=0;i<5;i++)
{
scanf("%d %s %s %s %f",&ph_arr[i].id,ph_arr[i].brand,ph_arr[i].mod,ph_arr[i].cpu,&ph_arr[i].price);
}
【4】结构体指针
1. 概念:
指向结构体变量的指针称为结构体指针
2.定义格式:
struct 结构体名 *结构体指针名;
应用:
struct phone
{
int id; //编号
char brand[10]; //品牌
char mod[20]; //型号
char cpu[20]; //处理器
float price; //价格
}ph_arr[5];
struct phone *p = ph_arr;
访问形式:
(*p).id = 1001;
p->id = 1001;
练习:打印功能选项,由用户进行功能选择,
例如:输入1,进行手机信息录入。
输入2,进行手机信息打印。
输入6,退出系统。
【5】共用体
1. 概念:
不同数据类型的数据使用共同的存储区域,这种数据构造类型称为共用体,又称联合体。
2. 定义格式:
union 共用体名
{
成员列表;
};
例如:
union data
{
char cval;
int ival;
float fval;
};
3.共用体类型变量定义:
(1)先定义共用体类型,后定义变量。
union data
{
char cval;
int ival;
float fval;
};
union data a,b,c;
(2)定义共用体类型的同时定义变量。
union data
{
char cval;
int ival;
float fval;
}a,b,c;
如果不再定义新的变量,也可以将共用体的名字省略:
union
{
char cval;
int ival;
float fval;
}a,b,c;
4.共用体大小计算:
结构体占用内存大于等于所有成员占用内存的总和,因为成员之间可能存在空隙,而共用体占用的内存空间,等于最大的成员变量占用的内存。
共用体采用了内存覆盖技术,同一时刻只能保存一个成员的值,如果对新的成员赋值,会覆盖掉原有的成员数据。
比如 :共用体data里占用内存最大的是int类型数据,占用4个字节,那么共用体data占用的内存大小为4。
union test
{
char s[20];
int b;
double c;
}a;
sizeof(a) = 20;
通过共用体验证大小端:
#include<stdio.h>
union test
{
char a;
int b;
}num;
int main(int argc, const char *argv[])
{
num.b = 0x12345678;
printf("%#x\n",num.a);
return 0;
}
【5】枚举:
1.定义:
只能取预先定义值的数据类型是枚举类型。
2.格式:
enum 枚举类型名
{
枚举元素列表
};
例如: 列出一个星期有几天:
enum week
{
Mon, Tues, Wed, Thurs, Fri, Sat, Sun
};
可以看到,我们仅仅给出了名字,却没有给出名字对应的值,
因为枚举值默认从0开始,往后逐个加1,也就是说,week 中的 Mon、Tues … Sun
对应的值分别为 0、1 … 6。
我们也可以给每个名字都指定一个值:
enum week
{
Mon = 1, Tues = 2, Wed = 3, Thurs = 4, Fri = 5, Sat = 6, Sun = 7
};
由于枚举类型值逐个递增1,我们也可以只给第一个名字指定一个值:
enum week
{
Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun
};
说明: 1)枚举类型是一种类型,通过它可以定义枚举变量
enum week a,b,c;
2)可以将列表里的值赋给枚举变量
enum week a = Mon, b = Web, c = Sat;
3)枚举列表中的Mon、Tues、Wed这些标识符的作用范围是全局的(严格来说是 main() 函数内部)
不能再定义与他们名字相同的变量。
4)Mon、Tues、Wed等都是常量,不能再次赋值,只能将他们赋给其他变量。
示例:判断用户输入的是星期几。
#include <stdio.h>
int main(){
enum week{ Mon = 1, Tues, Wed, Thurs, Fri, Sat, Sun } day;
scanf("%d", &day);
switch(day){
case Mon: puts("Monday"); break;
case Tues: puts("Tuesday"); break;
case Wed: puts("Wednesday"); break;
case Thurs: puts("Thursday"); break;
case Fri: puts("Friday"); break;
case Sat: puts("Saturday"); break;
case Sun: puts("Sunday"); break;
default: puts("Error!");
}
return 0;
}