结构体知识点

 

目录

1.结构体

1.1结构基本概念

1.2结构体

1.3结构体声明与定义

1.3.1结构体声明vs定义

1.3.2结构体声明与定义的几种形式

1.4例题

1.5使用结构体

1.6结构体的大小

1.6.1引言 

1.6.2内存对齐

1.7例题

2.联合体

2.1union

2.2联合体的意义

2.3例题

3.枚举类型

3.1enumerate

3.2枚举变量的整数值

3.3例题


1.结构体

1.1结构基本概念

“结构” struct ure
通过多个同种/不同种的部件,组成一个设备
每个部件本身都是 基础元件
形成的结构具有更高层级的 实际含义

1.2结构体

多个数据类型聚合形成一个 新数据类型
每个成员描述该新类型的一个属性
形成的新类型具有 新含义
类比 商品:Item
价格:float
存货:int
编号:long long
名称:char[]
struct Item
{
    long long id;
    int count;
    float price;
    char name[20];
};
//1.声明结构体类型
struct Item a;
//2.定义结构体变量
a.count = 10;
a.price = 3.5f;
printf("%.2f", a.price) 
//3.访问结构体变量的成员

1.3结构体声明与定义

1.3.1结构体声明vs定义

声明: declare 定义 :define
•声明declaration :让编译器知道 存在 这么一个事物(名字)
定义 defination :让编译器实际去生成一个东西
struct Item
{
    long long id;
    int count;
    float price;
    char name[20];
};
//结构体声明
struct Item a;
//结构体(变量)定义

1.3.2结构体声明与定义的几种形式

1. 先声明,后定义
struct Student
{
    char name[20];
    long long id;
    int age;
    float score;
};
//结构体声明
struct Item a;
//结构体(变量)定义

2. 声明结构体类型同时定义变量
struct Student
{
    char name[20];
    long long id;
    int age;
    float score;
}a, b, c;//声明结构体类型同时定义变量
struct Item d;//结构体(变量)定义
b.age = 20;
d.score = 85.5f;
typedef 关键字
typedef = type + define,意为为类型起别名
每次都写 unsigned long long,很长很烦对吧
没问题,给它起个 类型别名 即可,比如叫 uint64 挺好,简洁明了
typedef unsigned long long uint64;
uint64 a;//等价于unsigned long long a;
a = 0xFFFFFFFFFFFFFFFF;
printf("%ld", a);
typedef 并不是宏定义替换!
结构体声明与定义的几种形式: typedef 关键字
3. 先声明结构体类型,然后为它起别名,再使用这个别名
struct Student 
{
    char name[20];
    long long id;
    int age;
    float score;
};//结构体声明
typedef struct Student S;//给这个结构体类型起一个类型别名
S s1, s2;//使用这个别名定义变量
// 后续使用...
4. 声明结构体的同时给它起别名,使用这个别名
typedef struct Student 
{
    char name[20];
    long long id;
    int age;
    float score;
} S;//声明结构体的同时起一个类型别名S
S s1, s2;//使用这个别名定义变量
// 后续使用...
注意4.和2.有本质区别,4.本质是一个typedef语句,而2.本质是一个变量定义语句

1.4例题

Key 1 :结构体是一种自定义聚合数据类型,捏合了多个不同类型的成员,按名索引
Key 2 :结构体声明=>创造新数据类型;结构体定义=>创造新变量
1.下面哪项不是C语言的基础数据类型( C)
A.short
B.double
C.struct
D.void
分析:void指“空类型”,strruct 是自定义数据类型
2.以下代码_______了一个_______ (B )
A. 声明,变量
B. 声明,数据类型
C. 定义,变量
D. 定义,数据类型
struct ItemToSell
{
    long id;
    int count;
    float price;
};
Key 3 :typedef 语句的作用是:为类型起 别名
1. 有如右结构体声明和定义,其中,Item和tissue分别为( C)
A. 变量,变量
B. 数据类型,数据类型
C. 数据类型,变量
D. 变量,数据类型
typedef struct ItemToSell
{
    long id;
    int count;
    float price;
} Item;
Item milk,tissue;
2. 有如右结构体声明和定义,item 和 i1(A )
A. 都是变量,类型相同
B. 都是变量,类型不同
C. item是数据类型/i1是变量
D. item是变量/i1数据类型
struct ItemToSell
{
    long id;
    int count;
    float price;
} item;
typedef struct ItemToSell Item;
Item i1,i2;
3. 有如下代码段,则 sizeof(kk) 的值为( C)
A. 2
B. 4
C. 8
D. 产生编译错误
typedef unsigned long long uint64;
uint64 kk = 0xFFFFFFFF;

1.5使用结构体

初始化和使用结构体变量的成员
可以使用初始化列表 {...} 里的值 按顺序/按名字 为结构体的各个成员赋初值
使用 点运算符 . 访问结构体的成员
typedef struct Student
{
    char name[20];
    unsigned long long id;
    int age;
    float score;
} S;
S s1 = {"Mike", 2022196739, age : 19, score : 85.5f};
printf("%s, %ld, %d, %.1f", s1.name, s1.id, s1.age, s1.score);
输出:Mike, 2022196739, 19, 85.5
如果是这样呢?
S s2 = {"Mike", 2022196739};
printf("%d, %.1f", s2.age, s2.score);

输出:0, 0.0

1.6结构体的大小

1.6.1引言 

使用 sizeof 运算符获取结构体(变量)占据的内存大小
原则上,一个结构体所占大小应当等于其所有数据成员大小之和
但是凡提原则,必有例外!
typedef struct Date
{
    int year;
    int month;
    int day;
} D;
D day1 = {2022, 3, 10}, day2;
printf("%d, %d, %d, %d", sizeof(struct Date), sizeof(D), sizeof(day1), sizeof(day2));
输出:12, 12, 12, 12

1.6.2内存对齐

理论上,下例中结构体 struct Date 的大小是 4 + 4 + 4 + 1 = 13字节
但实测为16字节,原因是编译器会对结构体数据内容进行 内存对齐(提高效率)
通常是4字节对齐 即结构体大小为4的整数倍
typedef struct Date
{
    int year;
    int month;
    int date;
    char day;
} D;
D day1 = {2022, 3, 10,'4'}, day2 = {1949, 10, 1,'6'};
printf("%d, %d, %d, %d", sizeof(struct Date), sizeof(D), sizeof(day1), sizeof(day2));
输出:16, 16, 16, 16

1.7例题

Key 1 :定义结构体变量的同时可使用初始化列表{...},按序提供数据成员的初始值
Key 2 :内存对齐:结构体 S 的大小 X 满足 X ≥ sizeof(S) 且 X = 4k, k ∈ {1, 2, ...}
1. 将下列哪项填入(a) 能使结构体变量 stu 的年龄为10 (C )
A. {“Mike” , {88.5f, 95.f, 100.f}, 10}
B. {name : “Mike” , score : {88.5f, 95.f, 100.f}, age : 10}
C. {name = “Mike” , score = {88.5f, 95.f, 100.f}, age = 10}
D. {“Mike” , 88.5f, 95.f, 100.f, 10}
分析:命名初始化结构体成员数据需要使用 XXX: YYY 形式,而非 XXX = YYY
struct Student
{
    char name[13]; // 姓名
    float score[3]; // 语数英三科成绩
    int age; // 年龄
} stu = (a) ;
2. 接上题,sizeof(stu) 的值为( C)
A. 28
B. 29
C. 32
D. 36
分析:stu各项数据成员大小之和为 13 + 3 * 4 + 4 = 29,首个大于等于29的4的倍数是32

2.联合体

2.1union

联合体(共用体),类似于结构体,但是存在本质区别:叠叠乐
联合体是所有成员 共享 内存空间的结构体,可以想象成它们重叠在一起
因此一个联合体的大小等同于其 最大成员 的大小
类比:相当于吃饭时,几个手机叠放在一起
typedef union UserAddress
{
    AddressA a1; // 美国地址 大小=78
    AddressB a2; // 中国地址 大小=96
    AddressC a3; // 南极地址 大小=16
} Address;
Address a;
printf("%d, %d, %d", sizeof(union UserAddress), sizeof(Address), sizeof(a));
输出:96, 96, 96

2.2联合体的意义

为什么有了结构体还要有联合体?
场景1:各个成员 互斥 ,同一时间只有一项生效
场景2:同一个数据可以合起来解读,也可以 分开 多部分解读
联合体在内存资源紧张的平台(如嵌入式)广泛使用
union Integer {
unsigned int n;
unsigned short segment[2];
} a;
a.n = 0xAABBCCDD;
printf("%X, %X, %X", a.n, a.segment[0], a.segment[1]);
输出:AABBCCDD, CCDD, AABB
这不是字符串!是十六进制数值!
小端存储

 

2.3例题

Key 1 :联合体各个数据成员共享空间,其大小为最大成员的大小
1. 请写出下列值:
union stud
{
    short int num;
    char name[10];
    float score[5];
    double ave;
} c;
sizeof(c):_20_______
typedef struct KK
{
    short a[7];
    char ch;
} K;
K k;
sizeof(k):_16______
typedef union ACHAR
{
    char a;
    char b;
    char c;
} C;
C u;
sizeof(C):_____1____
Key 2 :联合体各个数据成员共享空间,对任意成员的修改都会反应到所有数据成员上
1. 运行在小端机器上,则该程序段输出的内容为(D )
A. y, y, d, s
B. a, y, d, s
C. , , , a
D. a, , ,
typedef union Flexible
{
    char ch[4];
    short sh[2];
    int n;
} F;
F f = {"yyds"};
f.n = 97;
printf("%c, %c, %c, %c", f.ch[0], f.ch[1], f.ch[2], f.ch[3]);
分析:使用 {“yyds”} 初始化 f 时实际上为 f.ch (一个 char [4] 数组) 赋初值 “yyds” ,但由于联合体各个数据成员是重叠的,即 f.n 和 f.ch 本质是相同 的4个字节,所以 f.n = 97 实际上将该联合体的4个字节修改为整数97的二进制值。由于运行于小端机器,即整数的高位存放于高字节,低位存 放于低字节,97的二进制值中有效部分为低位,存放于这4个字节的最前端的1个字节,即ch[0],另3个字节皆为0值,对应’\0’ ,即空字符

3.枚举类型

3.1enumerate

有些类型的取值天然就是 有限 集合:
月份、星期、物品种类、用户角色类型...
在程序中通过声明一个枚举类型来表示一个有限取值的概念
enum Day {Mon = 1, Tue, Wed, Thur, Fri, Sat, Sun};
enum Day day = Tue;
printf("%d, %d", day, Thur);
输出:2, 4
一个枚举类型的取值限定为有限个 整数不变量
由该类型定义的变量只能取这些不变量中的其中一个值

3.2枚举变量的整数值

枚举类型的整数不变量取值可以手动指定,不指定则默认递增
enum XXX {A = 1, B, C, D};
printf("%d, %d, %d, %d", A, B, C, D);
输出:1, 2, 3, 4
enum XXX {A = 1, B = 7, C, D};
printf("%d, %d, %d, %d", A, B, C, D);
输出:1, 7, 8, 9
enum XXX {A, B, C, D};
printf("%d, %d, %d, %d", A, B, C, D);
输出:0, 1, 2, 3
enum XXX {A = 1, B, C = 7, D};
printf("%d, %d, %d, %d", A, B, C, D);
输出:1, 2, 7, 8
enum XXX {A = -1, B, C, D};
printf("%d, %d, %d, %d", A, B, C, D);
输出:-1, 0, 1, 2
enum XXX {A = 1, B, C = -1, D, E};
printf("%d, %d, %d, %d, %d", A, B, C, D, E);
输出:1, 2,-1, 0, 1
但是这种写法考试只是单纯考知识点,现实中根本不会写这种代码,枚举的值应该不能有相同的,不然违背枚举的初衷

3.3例题

Key 1 :枚举类型enum声明一个有限的命名取值(整数)集合,限定其变量取值
1. 有如下代码段,若用户输入为1,则输出为(B )
A. ERROR: 1
B. WARN: 1
C. WARN: WARN
D. ERROR: ERROR
enum LogType {INFO = 0, WARN, ERROR};
typedef enum LogType T;
T t;
do { scanf("%d", &t); } while (t < INFO || t > ERROR);
if (INFO == t) printf("INFO: %d", t);
else if (WARN == t) printf("WARN: %d", t);
else if (ERROR == t) printf("ERROR: %d", t);

2. 接上题,sizeof(t) 的值为( D)
A. 1
B. 2
C. 3
D. 4
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源】:包含前端、后端、移动开发、操作系统、人工智能、物联网、信息化管理、数据库、硬件开发、大数据、课程资源、音视频、网站开发等各种技术项目的源码。包括STM32、ESP8266、PHP、QT、Linux、iOS、C++、Java、MATLAB、python、web、C#、EDA、proteus、RTOS等项目的源码。 【项目质量】:所有源码都经过严格测试,可以直接运行。功能在确认正常工作后才上传。 【适用人群】:适用于希望学习不同技术领域的小白或进阶学习者。可作为毕设项目、课程设计、大作业、工程实训或初期项目立项。 【附加价值】:项目具有较高的学习借鉴价值,也可直接拿来修改复刻。对于有一定基础或热衷于研究的人来说,可以在这些基础代码上进行修改和扩展,实现其他功能。 【沟通交流】:有任何使用上的问题,欢迎随时与博主沟通,博主会及时解答。鼓励下载和使用,并欢迎大家互相学习,共同进步。【项目资源
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值