| |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
-> C++知识库 -> 自定义类型:结构体、位段、枚举、联合 ------- C语言 -> 正文阅读 |
|
[C++知识库]自定义类型:结构体、位段、枚举、联合 ------- C语言 |
C语言中,7可以存放再整型变量中,'c' 可以存放在字符型变量中,3.14可以存放在浮点型变量中,一个学生有:姓名、年龄、性别、学号等。C语言中是否有这样一个可以存放学生的类型呢?答案是肯定的,这一种类型教自定义类型,本篇博客将和各位小兄弟一起学习C语言中的自定义类型,其中包括结构体、枚举、联合,跟着本篇博客学习完后,你对C语言的理解肯定会再上一个level! 1. 结构体
1.1. 结构体的声明及其初始化1.1.1.?结构体声明特殊的声明: ?注:匿名结构体类型只能使用一次,走后续的代码中无法再次使用该结构体类型 1.1.2. 结构体变量的定义和初始化
1.2. 结构体的自引用结构体的自引用光看这几个字好像很专业,但其实用大白话概括就是:结构体里包含同类型的结构体指针变量。接下来用一个例子带大家深刻理解理解。
1.3. 结构体的内存对齐
一个字符型数据在内存中占1个字节,一个整型数据在内存中占4个字节,那么上面这个结构体数据在内存中占几个字节呢?有的小兄弟可能会说,“简单,不就是将所有的结构体成员变量相加嘛”。这种想法就是一个大错特错,计算一个结构体数据的大小可不是简单的将所有结构体成员变量相加就得出来的,想要计算一个结构体数据的大小,首先要明白结构体的内存对齐是怎么一回事,继续跟随博客的脚步一起学习结构体的内存对齐吧!
读完上面四条规则,各位小兄弟对如何计算结构体的大小应该有了一定的了解,但光是文字化的规则还是略显生硬了点,有图有真相,下面通过几个例子再来解释解释结构体内存对齐到底是怎么一回事。 看了上面的图解如果你感觉你又行了不妨趁热打铁,依葫芦画瓢,计算以下两个结构体变量的大小。
>> sizeof(struct S2) = 8
>> sizeof(struct S3) = 16
使用 #pragma pack( ) 修改默认对齐数当我们在设计结构体类型时,结构体在对齐方式不合适的时候,我们可以使用#pragma pack( )来修改默认对齐数。 下面我们通过一段实例代码来进行讲解。
算一下修改默认对齐数后结构体类型S2的大小是多少。 >> sizeof(struct S2) = 6
总的来说,结构体的内存对齐是拿空间来换取时间的做法。 2. 位段
2.1. 什么是位段位段是在结构体中实现。 位段的“位”指的是比特位。 位段的声明和结构体是类似的,但也存在以下两个不同点:
位段可以灵活的按需给成员分配空间。 例如,当我需要一个整型变量flag来帮我判断真假时(1表示真,0表示假),实际上我只需要一个比特位的空间就可以达到判断真假的目的。若不使用位段,系统会为flag开辟一个整型的空间,也就是4个字节,32个比特位;若使用位段来对变量flag进行处理,可以做到只开辟一个比特位的空间,从而达到节省空间的目的。 2.2. 位段的内存分配上文我们学习了结构体的内存对齐,那么位段也有内存对齐吗?答案是肯定的,但在位段这里不是内存对齐,而是内存分配。想要搞懂位段的内存分配,就要熟悉位段内存分配的规则。
看完以上几行文字,总觉得懂了又没完全懂。别急,下面带入几个实例加上图解来深刻理解位段的内存分配到底是怎么一回事。
抛出了两个猜想,接下来就是验证哪个是正确的。 ?在Visual Studio 2022的环境下,程序的运行结果证实了猜想一是正确的。 也就是说,当剩余的比特位不足以为当前成员分配空间时,将剩余的比特位舍弃,再次开辟4个字节或1个字节的空间(开辟4个字节还是1个字节由成员的类型决定,位段的成员类型一般是同一类型)。 了解了位段对于剩余比特位的处理后,就已经可以计算出使用位段的自定义类型的大小了。 那么使用位段的自定义类型的数据在内存中又是如何存储的呢,接下来我们还是以struct S为例,就这个问题展开探讨。
首先提出一个猜想,假设位段在内存中存储数据时,先使用高地址处的空间,后使用低地址处的空间。 接下来我们用图例简单的分析我们的猜想,然后运行一段简单的代码来判断猜想正确与否。 ?在VS2022的内存监视窗口中证实了我们的猜想,至少在Visual Studio 2022的环境下是成立的。
2.3. 位段的跨平台问题
3. 枚举顾名思义枚举就是把可能的取值一一列举。
像以上这样的情况,可能的取值情况比较少的,可以使用枚举类型来解决相关的问题,若可能的取值较多,则不适合用枚举类型来解决问题。 3.1. 枚举类型的定义及使用
?以上定义的 enum Day 是枚举类型,{ }中的内容是枚举类型的可能取值,也叫枚举常量。 这些可能取值都是有数值的,默认第一个枚举常量的数值为0,往后依次递增1,当然如有特殊需要,可以在定义枚举类型的时候同时赋初值。 | 例 |
?若只对部分枚举常量赋初值,则其余枚举常量还是往后依次递增1。 | 例 |
3.2. 枚举的优点通过上面的学习我们了解到,枚举列举的是其可能的取值,所有可能的取值都是一个常量,我们也能使用 #define 定义常量,那为什么我们还要使用枚举类型呢?
4. 联合 (共用体)什么是联合,为什么又叫共用体?接下来就和大家一起扒扒联合的底子。 联合也是一种特殊的自定义类型,这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间 (所以联合也叫共用体) 。 4.1. 联合类型的定义?
4.2. 联合的特点
以上这个联合类型的大小是多少呢?以我们常规思路来看,整型变量i占4个字节,字符型变量c占一个字节,怎么说这个联合的大小也得5个字节吧。 ?当我们把程序运行起来后,发现这个联合类型的大小为4个字节,这一点确实印证了我们刚刚描述的联合的特点,但是为什么是4个字节呢?别着急,我们继续往下探讨。 ?如何证明联合类型中的成员都共用同一块内存空间呢?这里采用的方法是将联合类型u的地址,联合类型u中成员i的地址,联合类型u中成员c的地址分别打印出来,观察这三个地址的情况。
当程序运行起来后,可以发现这三个地址是一模一样的。这又该如何解释呢? 下面通过图解来解释对上述情况。 ?由上图分析可以看出,成员i和成员c至少在第一个字节上是重叠的,共用了第一个字节的空间,所以这种结构类型也叫共用体。 由于联合的特性,各成员都共用一块内存空间,导致在使用联合类型时,只能使用众多成员中的一个。例如,当我们使用联合类型u的时候,我们使用成员i时,不能使用成员c;使用成员c时,不能使用成员i ( 当我们使用成员i时,给i赋值,同时使用成员c,给c赋值的同时会将成员i第一个字节的数据给覆盖掉,从而导致了成员i的值被修改这一情况?) 。 仅用文字来描述上述的情况还是不够直观,我们还是用一个简单的程序来验证一下联合的特性。 在调试中的内存窗口可以发现,执行完第15行代码后,联合类型u的4个字节内存空间中存储了成员i的值,当执行完第16行代码后,联合类型u的内存空间中第一个字节的数据被成员c的值覆盖了,有图有真相,联合类型中的各成员共用同一块内存空间,这一结论是属实的。 4.3. 联合大小的计算
| 例1 |
| 例2 |
本次与大家一起探讨C语言中的自定义类型 ( 结构体、位段、枚举、联合?) 到这就已经接近尾声了,期待下次与你相遇。 < 你的关注,点赞,评论,收藏都是对我创作最大的鼓励 >? ( 若本篇博客存在错误,望指出,感谢!?)? |
|
C++知识库 最新文章 |
【C++】友元、嵌套类、异常、RTTI、类型转换 |
通讯录的思路与实现(C语言) |
C++PrimerPlus 第七章 函数-C++的编程模块( |
Problem C: 算法9-9~9-12:平衡二叉树的基本 |
MSVC C++ UTF-8编程 |
C++进阶 多态原理 |
简单string类c++实现 |
我的年度总结 |
【C语言】以深厚地基筑伟岸高楼-基础篇(六 |
c语言常见错误合集 |
|
上一篇文章 下一篇文章 查看所有文章 |
|
开发:
C++知识库
Java知识库
JavaScript
Python
PHP知识库
人工智能
区块链
大数据
移动开发
嵌入式
开发工具
数据结构与算法
开发测试
游戏开发
网络协议
系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程 数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁 |
360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 | -2024/11/27 7:41:55- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |