构造数据类型
目录
一、结构体
1. 类型定义
// 结构体的通用定义格式:
// struct 结构体名 {
// 数据类型1 成员变量1; // 描述事物的第一个属性
// 数据类型2 成员变量2; // 描述事物的第二个属性
// 数据类型3 成员变量3; // 描述事物的第三个属性
// ...
// };
/*
* 日期结构体:用于表示一个具体的日期
* 包含年、月、日三个属性
*/
struct date {
int year;
int mon;
int day;
};
/*
* 时间结构体:用于表示一个具体的时间点
* 包含时、分、秒三个属性
*/
struct time {
int hour;
int min;
int sec;
};
/*
* 学生信息结构体:用于表示一个学生的基本信息
* 包含姓名、性别、年龄和成绩四个属性
*/
struct student {
char name[32]; // 字符数组,最多存储31个字符,预留1个位置给字符串结束符'\0'
char sex;
int age;
int score;
};
2. 结构体变量定义
存储类型 数据类型 变量名;
3. 结构体元素初始化
1)全部初始化
struct student {
char name[32];
char sex;
int age;
int score;
};
struct student stu = {"zhangsan", 'm', 18, 90};
2)局部初始化
■ 没有给定初值的元素都被赋值为0
struct student stu = {
.name = {"zhangsan"},
.score = 90,
};
4. 结构体成员访问
● . :结构体变量类型访问成员变量 .
● -> :结构体指针类型访问成员变量 ->
● 结构体访问成员变量最终的类型由成员变量的类型决定
5. 结构体的存储(内存对齐)
● CPU访问内存时,按 "块" 读取(如32 位CPU 每次读4字节),对齐的地址能减少访 问次数(1次完成),未对齐地址可能需要2次访问,降低效率。
● 结构体成员必须存放在内存地址为自身类型长度整数倍的内存单元中
● 结构体的大小必须为自身最大类型长度的整数倍
struct student {
char name[32]; //char 数组,无需对齐,连续占用 32 字节
char sex; //单个char,占1字节,但后续需要填充3字节,才能让age(int)从4的倍数地址开始
int age; //int本身已按 4 字节对齐,无需额外填充
int score; //int本身已按 4 字节对齐,无需额外填充
};
//总大小 44 字节是 4 的倍数,满足结构体整体对齐要求
6. 结构体传参
● 传地址更好,因为实参将8字节拷贝给形参,避免结构体大空间的拷贝
■ 传值
void fun(struct student tmp);
■ 传地址
void fun(struct student *ptmp);
7. 结构体数组
● 数组元素个数必须是常量
数据类型 数组名[元素个数];
8. 结构体数组初始化
struct student s[3] = {
{"zhangsan", 'm', 19, 100},
{"lisi", 'f', 18, 90},
{"wanger", 'm', 19, 60},
};
struct student s[3] = {
[1] = {
.name = "zhangsan",
.score = 90,
},
};
9. 结构体数组传参
int fun(struct student *pstu, int len);
二、共用体
1. 共用体也称为联合体
● 共用体每个成员变量的空间共享的
● 结构体每个成员变量的空间是独立的
● 多用于函数传参使用
2. 数据类型定义
union 共用体名 {
数据类型1 成员变量1;
数据类型2 成员变量2;
数据类型3 成员变量3;
...
};
3. 使用共用体判断内存大小端
● 内存低地址存放低数据位,内存高地址存放高数据位,内存小端
● 内存低地址存放高数据位,内存高地址存放低数据位,内存大端
int Num = 0;
Num = 0x11223344;
● 小端存储:多字节数据的低位字节存储在低内存地址,高位字节存储在高内存地址
● 大端存储:多字节数据的高位字节存储在低内存地址,低位字节存储在高内存地址
4. 判断硬件平台是内存大端还是小端
#include <stdio.h>
//定义一个共用体
union s {
char a; //字符型成员,占用1字节(存储在共用体内存空间的最低地址处)
int b; //整型成员,占用4字节(覆盖共用体的整个内存空间)
};
int main(void)
{
union s s1; //声明一个共用体变量s1,分配4字节内存空间(由最大成员int决定)
s1.b = 1; //给整型成员b赋值1,内存中表示为二进制:00000000 00000000 00000000 00000001
//注意:不同端模式下,这4个字节在内存中的排列顺序不同
//访问字符型成员a:只会读取共用体内存空间的第一个字节(低地址字节)
//如果是小端模式:低地址存储低字节 → 第一个字节是00000001(值为1,非0)
//如果是大端模式:低地址存储高字节 → 第一个字节是00000000(值为0)
if(s1.a)
printf("小端存储\n"); //s1.a非0,说明是小端模式
else
printf("大端存储\n"); //s1.a为0,说明是大端模式
return 0;
}
三、枚举
1. 枚举定义一些枚举常量
2. 定义形式
enum 枚举类型 {
常量1,
常量2,
常量3,
...
};
3. 特性
● 枚举常量均为int类型,且第一个枚举常量的值默认为0,后续枚举常量的值总是前一个 常量的 值+1
● 枚举常量可以在定义时被赋值
● 提高可读性,如下:用 SUNDAY 比用 0 更直观。
//枚举常量默认从0开始递增(Sunday=0, Monday=1, ..., Saturday=6)
enum Weekday {
Sunday, //枚举常量:值默认为0
Monday, //枚举常量:值默认为1
Tuesday, //枚举常量:值默认为2
Wednesday, //枚举常量:值默认为3
Thursday, //枚举常量:值默认为4
Friday, //枚举常量:值默认为5
Saturday //枚举常量:值默认为6
};