当前位置: 首页 > news >正文

C语言第22讲

目录

自定义类型:结构体

        结构的自引用

        结构体在内存中开辟空间的流程

结构体实现位段

位段的内存分配:

自定义类型:联合

自定义类型:枚举     


自定义类型:结构体

结构体的初始化和使用:

 #include <stdio.h>struct Stu{char name[20];//名字int age;//年龄 char sex[5];//性别 char id[20];//学号 };int main(){//按照结构体成员的顺序初始化struct Stu s = { "张三", 20, "男", "20230818001" };printf("name: %s\n", s.name);printf("age : %d\n", s.age);printf("sex : %s\n", s.sex);printf("id  : %s\n", s.id);//按照指定的顺序初始化struct Stu s2 = { .age = 18, .name = "lisi", .id = "20230818002", .sex = "⼥" };printf("name: %s\n", s2.name);printf("age : %d\n", s2.age);printf("sex : %s\n", s2.sex);printf("id  : %s\n", s2.id);return 0;}

匿名结构体:当我们去掉其结构体名称时就是匿名结构体

这类特殊结构体变量的创建需要即使创建

下图为一错误示范

虽然我们知道是同类型,但是因为是匿名结构体,所以编译器无法分辨所以会报错

下图为拖裤子放屁炒作:

将匿名数组重命名,导致匿名数组不在值使用一次

        结构的自引用

                数组是在内存中连续开辟空间存放内容也称顺序表

链表:

                数据在空间中随机存放但是,每个数据都有下一个数据的地址,导致可以找寻到下一个数据内容。如图这般:

                结构体的自引用功能和上述类似

代码如下:

 struct STU
{char name[20];struct STU* next;
};

自己能引用和自己同类型的对象(匿名结构体不能自引用)

        结构体在内存中开辟空间的流程

结构体对齐内存:

问题:下方代码运行结果

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>struct S
{char a;int b;char c;
}s = {0};int main()
{printf("%zd",sizeof(s));  // 12return 0;
}

对齐规则:

                1.结构体第一个成员名对齐到结构体变量起始位置偏移量为0的地址处

                2.其它变量要对齐到某个数字(对齐数)的整数倍的地址处

                                对齐数:编译器默认一个对齐数与该成员变量内存,中较小的值

                                VS默认为 8

                                linux 中gcc 没有对齐数,对齐数是成员自身大小

                在上图中我们得到了最终内存大小为9,但还有最后一步

                3.结构体总大小必须为最大对齐数的整体倍数

                int b > char a 和c  为4 所以最终为 12

问题1:以下代码运行结果

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>struct S
{char c1;char c2;int  a;
}s = {0};int main()
{printf("%zd",sizeof(s));return 0;
}

                如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构体的整体大小就是所有对齐数中最大的倍数(包含被嵌套的结构体中的成员对齐数)

问题2:以下代码运行结果

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>struct S
{char c1;char c2;double  a;
};struct M
{int a;struct S s;char c;
};int main()
{printf("%zd",sizeof(struct M));  // 32return 0;
}

问题3:以下代码运行结果

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>struct S
{int arr[7];char c2;double  a;
};int main()
{printf("%zd", sizeof(struct S));return 0;
}

                数组按元素对齐一次就行,后面按顺序排列

让占用空间小的成员尽量集中在一起可以做到节约空间

                实际上我们可以更改默认对齐数

                利用 #pragma 

#pragma 的使用:

// 修改默认对齐数为1
#pragma pack(1)     // 推荐设置为 2的次方// 取消设置,还原默认
#pragma pack()

结构体实现位段

                当写代码时,一个 int 类型的变量只是接受 0 和1 两个参数时,只需要1个bit位就能解决时,就可以使用位段,减少内存的消耗

位段的实现:

// 结构体
struct S
{int a;char c1;char c2;
};
// 位段
struct M
{int a:8;char c1:2;char c2:2;
};

                位段和结构体的差距只在变量和冒号之间多了个 分号和数字

                数字的意义表示 需要 多少 的内存 大小为 bit 位

                这里说明,位段设计很多不确定因素,位段是不跨平台的,注重可抑制的程序应该避免使用位段

位段的内存分配:

问题:以下代码运行结果是什么

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>struct S
{char a : 3;char b : 4;char c : 5;char d : 6;
};int main()
{printf("%zd", sizeof(struct S));return 0;
}

运行结果:

                由于C语言没有规定位段的使用,所以会存在两处分歧

                1.单个字节是从哪里开始使用

                2.剩余空间不足下一个成员使用,是浪费还是给下一个成员用

上题在VS的存储逻辑如下图:

                位段成员没有地址

                不能对位段成员使用&操作符,这样就不能使用scanf直接给位段成员输入值了,只能通过先输入存放在一个变量中,然后赋值给位段成员

                只能在结构体中使用位段

自定义类型:联合

联合体关键词 union

                编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员公用一块空间。所以联合体也叫:共用体

下方代码能侧面验证使用同一块空间:

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>union UN
{char c;int i;
};int main()
{union UN un = { 0 };printf("%zd\n", sizeof(un));printf("%p\n", &un);printf("%p\n", &un.c);printf("%p\n", &un.i);return 0;
}

问题:以下代码运行最终结果是什么

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>union UN
{char ch[5];int i;
};int main()
{union UN un = { 0 };printf("%zd\n", sizeof(un));return 0;
}

                字符数组 5(1) 和整形 4 共用同一块空间,但是也遵循总内存是最大对齐数的倍数

                4 > 1 最大对齐数为4

                4*1 < 5 < 2*4 最终总空间大小为4

问题:⽐如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。 每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

·图书:书名、作者、⻚数

·杯⼦:设计

·衬衫:设计、可选颜⾊、可选尺⼨

                我们可以将所有元素归纳到结构体中,但是由于各个商品的特殊性,会导致内存空间浪费,所以可利用上方结构体将每个商品的特殊元素,规整到一个空间中

代码如下:

struct gift_list
{   // 公共属性int stock_num;				// 库存量double price;				// 定价int item_type;				// 商品类型// 特殊属性union{struct{char title[20];		// 书名 char author[20];    // 作者int num_pages;      // 页数}book;struct{char designe[30];   // 设计}mug;struct{char designe[30];   // 设计int colors;			// 颜色int sizes;			// 尺寸};};
};

问题:设计一个判断大小端的程序

#define _CRT_SECURE_NO_WARNINGS 
#include <stdio.h>union S
{char a;int i;
}s;int mian()
{s.i = 1;printf("%d", (int)s.a);return 0;
}

自定义类型:枚举     

枚举的关键词 enum

枚举的使用:

enum Day//星期
{Mon,      // 0Tues,     // 1Wed,      // 2Thur,     // 3Fri,      // 4Sat,      // 5Sun       // 6
};
int main()
{enum Day d = Sun;return 0;
}

                后方为逗号 

                enum Day 是类型    Mon,Tues,Wed,Thur,Fri,Sat,Sun是他的元素

                char 的元素是 ASCII表 枚举的元素也类似,实际 Mon为0后续元素依次+1

如果给莫个元素赋值,前方不变,后方延赋值+1依次下去

enum Day//星期
{Mon,      // 0Tues,     // 1Wed = 5,  // 5Thur,     // 6Fri,      // 7Sat,      // 8Sun       // 9
};

                枚举常量遵循作用域规则

http://www.dtcms.com/a/407510.html

相关文章:

  • 神经网络二分类任务详解:前向传播与反向传播的数学计算
  • 慈溪网站建设慈溪如何建设盈利网站
  • 免费网站软件app做网站 如何注册公司
  • 制作网站培训网页布局有哪几种
  • 给一张立方体图片的斜视图,对着图片建模的ppo模型,架构怎么设计 solidworks
  • Kafka 面试题及详细答案100道(51-65)-- 性能优化与调优
  • 高要seo整站优化wordpress边框
  • 岐山县住房和城市建设局网站企业网站的推广阶段和特点
  • vue前端项目使用摄像头扫码时需要访问https服务接口,访问自建证书出现接口报错,可能在你的电脑上安装证书
  • 设置环境变量时避坑:不要引号不要空格,如:set API_KEY=.....
  • C++设计模式_创建型模式_单件模式
  • 进阶:基于 dlib 的 68 点人脸关键点检测实现
  • 设计师培训心得北京seo诊断
  • (超详细,于25年更新版) VMware 虚拟机安装以及Linux系统—CentOS 7 部署教程
  • 微信兼职平台网站开发多个域名多国语言网站seo优化
  • JavaScript逆向补环境逆向WASM的思路
  • Android 13.0 Framework 实现应用通知使用权默认开启的技术指南
  • 厦门网站的关键词自动排名大都会app可以删记录吗
  • 网站优化标题百姓网免费发布信息网下载
  • DaemonSet使用示例
  • 台州建网站北京装饰公司电话
  • docker容器的三大核心技术UnionFS(下)
  • 4.6 BRDF
  • Python GIL全局解释器锁技术演进
  • 小学老师在哪个网站做ppt做羊毛毡的网站
  • 模块化神经网络
  • Python多线程:让程序 “多线作战” 的秘密武器
  • 黟县方坑岭影视基地三剧连拍开机 《生死制暴》影视赋能乡村振兴
  • 微信网站打不开海南搜索引擎优化
  • 国产化(银河麒麟_海光CPU)消息中间件选型及安装