| |
|
开发:
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语言——自定义类型(结构体,枚举,联合体,位段) |
目录 结构体结构体的定义结构是一些值的集合,这些值称为成员变量。结构的每个成员可以是不同类型的变量
其中struct Stu是自定义结构体类型,花括号内的一系列数据类型称为结构体成员,student为定义的结构体类型变量。 匿名结构体
在声明结构的时候,可以不完全的声明,上面的两个结构在声明的时候省略掉了结构体标签。在上面代码的基础上,下面的代码是不合法的。因为,当两个结构体的类型相同时,才可以用同类型的结构体指针来接收同类型的结构体地址。但是,这两个是匿名结构体,特殊的声明,虽然结构体的成员都是一样的,但是在编译期看来,这两个结构体是不一样的。 结构体的自引用
直接将结构体嵌套在相同结构体是不可取的,你可以想象一下,如果可以这么做,那这个结构体的大小是多少,他会无限制地嵌套下去,导致栈溢出,如果硬是需要嵌套自身,应该嵌套相同结构体类型的指针。
用typedef定义新类型名来代替已有类型名,即给已有类型重新命名。 举例说明:
?使用typedef来命名一个结构体类型是可以省略的,因为typedef引入了标签;上面代码中的STUDENT不是结构体变量,而是创建了一个使用的标签。在这基础上,我们来看下面的代码。
这个代码中,使用typedef将结构体重命名为Node,但是在结构体内部却先使用了Node这个结构体类型名,所以这个代码是错误的。
这才是正确的代码。如果我们要用到自定义结构体的时候,我们需要把标签也就是结构体类型名先定义出来。 结构体的使用与传参
输出结果
对于结构体传参,尽量使用结构体指针传参,因为直接传结构体,当结构体很大时,会占用大量栈区的空间,甚至导致栈溢出。 结构体大小计算我们先介绍第一个概念,偏移量。 计算机汇编语言中的偏移量定义为:把存储单元的实际地址与其所在段的段地址之间的距离称为段内偏移,也称为"有效地址或偏移量"。 ?接下来开始讲解计算如何计算结构体大小。 结构体的大小不是将所有成员变量的大小加起来这么简单,实际上在内存中各成员是需要对齐的,在vs编译器中默认对齐值为8,在其他的编译环境中可能没有默认值,也可以默认值是其他的值。
结构体的对齐规则:
对于S3,第一个成员总是放在结构体偏移量为0的位置。所以偏移量0-7的位置放的是double类型的d成员。char c的对齐数位1。所以放在偏移量为8的地址处就可以了。int i的对齐数是4,除了第一个成员变量要对齐到某个数字(对齐数)的整数倍的地址处。int i就只能放在偏移量为12的地址处,并且占4个字节。如下图所示,S3共占16个字节。 对于结构体S4,char c1是第一个成员,所以它放在结构体的起始位置,也就是偏移量为0的位置,占一个字节。如果嵌套了结构体的情况,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。S3的最大对齐数是8,所以S3只能放在偏移量为8的地址,且占16个字节。最后一个double d对齐数是8,放在偏移量为24的地址,占8个字节。S4的大小为32个字节。 ? 那为什么需要对内存对齐呢? 1、平台原因(移植原因): 位段位段,也称位域,C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为"位段"或称"位域"( bit field) 。利用位段能够用较少的位数存储数据。 位段的声明和结构是类似的,有两个不同
那位段的在内存中占多少字节呢? 位段的内存分配 我们已经知道了位段是如何开辟内存的,接下来再来看一段代码,了解位段是如何存放数据的。
? ? ?内存中开辟的空间如图所示。s.a = 10;s.b = 12;a的二进制表示为1010,b的二进制表示为1100,但是a在位段中只分配了3个bit位。所以,只能存放后三位010。 同理,c和d在内存中如图所示。 ? 跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。 位段的应用: 枚举枚举概念enum,枚举在C/C++/c#,还有Objective-C中,是一个被命名的整型常数的集合,枚举在日常生活中很常见。例如表示星期的SUNDAY, MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY,SATURDAY, 就是一个枚举。枚举的说明与结构和联合相似。 枚举的声明与使用
以上定义的 enum Day , enum Sex , enum Color 都是枚举类型。
枚举常量,默认第一个成员是0,从后面依此递增。但是,成员定义的时候可以赋初值,GREEN = 5,从这个成员之后,在这个GREEN的基础之上,依此递增,也就是BLUE = 6。 枚举的使用
枚举大小计算枚举变量的大小还是枚举成员的大小,都是存储一个整型的数据。所以枚举类型变量占4个字节。
枚举与宏的区别使用枚举定义的枚举常量是有类型的,为枚举类型,而使用#define宏是替换,并没有枚举类型这种性质。 增加代码的可读性和可维护性 联合体联合体的概念在进行某些算法的C语言编程的时候,需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术,几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构,在C语言中,被称作"共用体"类型结构,简称共用体,也叫联合体。 联合体的声明与使用关键字? union
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
输出结果为:
联合体大小计算1、联合的大小至少是最大成员的大小。 2、当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
联合体Un1最大成员大小为5,char类型对齐数为1,int类型对齐数为4,所以最大对齐数为4,联合体大小应为最大对齐数的整数倍,大小为8。
|
|
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/24 1:30:36- |
|
网站联系: qq:121756557 email:121756557@qq.com IT数码 |