一、结构体
- 结构体:是一种构造数据类型,可以预先设计类型,该类型可以是由多个不同的类型组成。其各个成员存储是连续的。
- 结构体的定义:
- 结构体类型定义:不存在内存空间,只有将类型定义为具体的变量时,其内存空间才存在。通常类型定义都放在函数外。
- 结构体的类型:类型相同的问题:结构变量类型要相同,必须是同一个类型名,定义结构体变量才是类型相同,仅仅是里面成员相同是不行的;两个结构体变量相同类型时,可以直接赋值,区别于数组。
struct 类型名{
成员列表
};
#include <stdio.h>
//定义结构体
struct student
{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
};
- 结构体变量定义:通过结构体类型定义的变量。
struct 类型名 变量名;
#include <stdio.h>
//定义结构体
struct student
{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
};
int main()
{
struct student zhangsan = {"张三","男","class1",1,1.80};
return 0;
}
- 结构体变量的初始化:与数组类似。
- 整体初始化
- 对成员变量初始化:使用成员访问运算符:“.”。
- 定义类型时定义变量并初始化
#include <stdio.h>
//定义结构体
struct student{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
};
//定义类型时定义变量并初始化
struct student1{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
}wangwu = {"王五","男","class1",2,1.76};
int main()
{
//整体初始化
struct student zhangsan = {"张三","男","class1",1,1.80};
//单独对其成员变量赋初始值
zhangsan.hight = 1.60;
return 0;
}
- 无名结构体:结构体变量的类型没有没有名字,通常表示这是一个类型的唯一变量
#include <stdio.h>
//定义无名结构体
struct{
//姓名
chr name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
}wangwu = {"王五","男","class1",2,1.76};
- 结构体变量成员的访问:使用结构体变量成员访问运算符:“.”。
结构体变量名.成员名;
- 遍历结构体
#include <stdio.h>
//定义结构体
struct student{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
};
//遍历结构体
void showstruct(struct student a)
{
printf("%s %s %s %d %.2f\n",a.name,a.sex,a.class,a.id,a.hight);
}
int main()
{
//整体初始化
struct student zhangsan = {"张三","男","class1",1,1.80};
showstruct(zhangsan);
return 0;
}
- typedef:给类型取别名。关键字。
格式:typedef 原数据类型 别名;
- 与#define的区别:宏替换,常量替换,在预处理阶段执行,不会报错;而typedef是在编译时执行。
#include <stdio.h>
typedef unsigned int uint_t;
//定义结构体,并取别名
typedef struct student
{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
}student_t;
//遍历结构体
void showstruct(struct student a)
{
printf("%s %s %s %d %.2f\n",a.name,a.sex,a.class,a.id,a.hight);
}
int main()
{
//整体初始化
struct student zhangsan = {"张三","男","class1",1,1.80};
showstruct(zhangsan);
student_t wangwu = {"王五","男","class1",2,1.76};
showstruct(wangwu);
return 0;
}
- 结构体的存储模型(内存图):
通过程序查看结构体变量的内存地址:
#include <stdio.h>
typedef unsigned int uint_t;
//定义结构体,并取别名
typedef struct student
{
//姓名
char name[10];
//性别
char sex[10];
//班级
char class[20];
//学号
int id;
//身高
float hight;
}student_t;
int main()
{
printf("size = %ld\n",sizeof(student_t));//结果:size = 48
student_t zhangsan;
printf("zhangsan = %p\n",&zhangsan);
printf("zhangsan.name = %p\n",&zhangsan.name);
printf("zhangsan.sex = %p\n",&zhangsan.sex);
printf("zhangsan.class = %p\n",&zhangsan.class);
printf("zhangsan.id = %p\n",&zhangsan.id);
printf("zhangsan.hight = %p\n",&zhangsan.hight);
return 0;
}
程序运行结果:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ex09kB0T-1655466973576)(F:\华清嵌入式\嵌入式学习\C语言\Linux基础与C高级\C语言高级\C语言高级Day03\结构体变量内存地址.png)]
- 字节对齐:系统为了方便快速的定位内存中的变量,引入字节对齐的操作。该操作规定:数据存储位置(地址)必须是其类型的整数倍。
数据类型 | 存储空间 | 内存地址 |
---|---|---|
int、float类型 | 4字节 | 存储位置的首地址必须以0、4、8、c被4整除。 |
short类型 | 2字节 | 存储位置的首地址必须以0、2、4、6、8、a、c、e结尾。 |
char类型 | 1字节 | 任何地址都可以作为char类型的起始位置。 |
- pragma pack(n):指定编译器字节对齐模式,n可以缺省,代表默认4字节。
二、结构体数组
- 结构体数组:用于多个存储结构体类型的变量。
- 结构体数组的定义:结构体类型(struct 结构体变量名)数组名[数字];
- 结构体数组初始化:通过访问结构体成员变量,进行赋值。
- 结构体数组的遍历:可以使用数组遍历方式,也可以使用指针的方式遍历。
三、结构体指针
- 结构体指针:指针指向结构体
- 结构体指针访问:
- ->:结构体指针成员访问符。
- .:结构体变量成员访问符。
#include <stdio.h>
//定义结构体,并取别名
typedef struct student
{
//姓名
char name[10];
//学号
int id;
//成绩
int grade;
}student_t;
int main()
{
struct student arry[3];
char buf[20];
int i;
//数组方式遍历结构体数组
for(i = 0; i < sizeof(arry)/sizeof(arry[0]); i++)
{
printf("请输入第%d个学生的姓名:",i+1);
scanf("%s",arry[i].name);
printf("请输入第%d个学生的学号:",i+1);
scanf("%d",&arry[i].id);
printf("请输入第%d个学生的姓名:",i+1);
scanf("%d",&arry[i].grade);
fgets(buf,sizeof(buf),stdin);
}
struct student *p = arry;
//指针方式遍历结构体数组打印输出
/*
for(i = 1; i <= sizeof(arry)/sizeof(arry[0]); i++)
{
printf("name:%s\tid:%d\tgrade:%d\n",(*p).name,(*p).id,(*p).grade);
p++;
}
*/
for(i = 1; i <= sizeof(arry)/sizeof(arry[0]); i++)
{
printf("name:%s\tid:%d\tgrade:%d\n",p->name,p->id,p->grade);
p++;
}
return 0;
}
四、共用体
- 共用体:多个数据类型公用同一片内存空间,该空间的大小由最长那个成员决定;数据有效性,由最后赋值的那个成员决定。
- 共用体类型定义:
union 共用体类型
{
成员列表
};
- 变量定义:union 共用体类型 共用体变量
- 共用体成员访问:与结构体成员变量访问完全一致。
- 字节序:对于基本数据类型中多字节数据存储,由CPU结构决定。
- 小端字节序:高字节存放高位,低字节存放低位。PC X86架构
- 大端字节序:高字节存放低位,低字节存放高位。ARM架构。
五、枚举类型
- 枚举:就是对一些常量进行定义
- 枚举类型的定义
enum 类型名
{
常量列表
};
- 枚举变量的定义:enum 枚举类型名 变量名;
- 枚举类型访问:读取按整型即可。