【C语言】自定义类型

news/2024/7/5 5:21:22

前言

男孩子在外面要保护好自己~


一、结构体

为什么会有结构体呢?但要描述一个复杂对象时,仅用之前学过的基本数据类型表达不了(如:我要描述一个人,仅靠基本数据类型只能说定义他的一种属性<如用 int 定义他的年龄>),这时能不能说定义一个人,可以把他的多种属性(年龄,名字等)放到一起

1、结构体的基本格式

一个结构体里面首先有结构体名,结构体变量,成员变量名(属性)

struct 结构体名

{

成员变量;

} 结构体变量 ; (易错:分号一定不能丢)

结构体变量在其声明后的作用域中定义;

2、结构体的声明

这样就做到了结构体变量的声明(定义了 结构体名字 和 成员变量)

结构体的知识可联想 游戏 人物类型的创建:

结构体名相当于 游戏里的 人物类型名称(如开普勒斯里的 人类<一种人物类型>)

结构体的成员变量 相当于该种族中的人物所拥有的属性 (如上图有攻击力、血量等)

结构体变量,就相当于我们在该种族中的一个人物

定义了人物,就拥有了其相关属性,我们可以定义人物属性,这样就能做到定义游戏里的人物种族,人物及其属性

3、结构体变量

结构体变量可以定义在声明的花括号后,也可以定义在结构体声明后的作用域中定义(如下图)

    • 成员变量的访问(引用)

两种方式:(如下图)

一种是当非指针类型结构体变量访问时, 用 点来进行访问成员变量

一种是当 指针类型结构体变量访问时,用 -> 来进行访问成员变量

并且点( . )与箭头 ( -> ) 是固定配套使用的

非指针型 ———— . + 成员变量

指针型 ———— -> + 成员变量

其结果都为:

    • 结构体对其数和结构体大小

1、第一个成员从偏移量下标为 0 开始存不用说

2、除了第一个成员,其他成员储存时 储存位置的下标 必须是 该成员 对其数的倍数

  1. 结构体总大小 是所有成员对其数中 最大对其数的倍数

注:

如果一个结构体里嵌套了结构体, 内部的结构体储存时,储存位置的下标 是 该结构体自身最大对其数 的倍数

(不管是储存时,还是计算整体大小时,都要细分细看)

为何如此分配空间:

(1)移植原因

(2)效率更高:是一种用空间来换取时间的方法

如何修改默认对其数:

用 #pragma pack()

#pragma pack( 新设置的默认对其数 )

如果想重置默认对其数

再写一遍:#pragma pack()

etc.

6、结构体传参

结构体传参时,可以直接传结构体,也可以传结构体的地址

但是两种都为优选吗?并不见得

想想如果一个结构体空间很大,如果直接传结构体本身到函数,内存中会发生什么?

内存中也要开辟和结构体同样大的栈帧空间,如果结构体很大,那么程序的性能也必将下降(栈痛哭:栈不要钱的吗?)

但是如果传结构体的地址呢?大小只有 4或8 个字节,开销相比不会那么大,一定程度提升了性能(栈对指针可能有意思哦)

所以一般设计结构体传参时,一般考虑传结构体地址而不是直接传整个结构体

位段

位段,也是结构体的一种,明显的只是内存分配上的差异

相比结构体

优点:节省空间

缺点:跨平台问题

基本格式是在 “ 成员变量 : 数字 ” 的形式

etc.

如果按正常的char类型来说,该结构体大小应该为3,而使用了位段让改结构体大小为 2,现研究一下位段的内存的分配问题

位段的内存分配

环境不同,位段内存分配方式可能不同;在我们的VS环境底下,对位段的内存分配:

(1)空间按 1 个或 4 个字节的方式开辟。int类型 一下开辟四个

(2) 一个字节空间里,若放得下一个完整的位段就放,放不下就换另一个字节

(3)整个结构体大小也是其成员最大对其数的倍数

位段的跨平台问题

不同的编译器对位段的内存分配可能不同,也有很多其他不确定性因素,所以一致性很差,不能跨平台,可执行程序避免使用位段(没什么事掌握的前提下就不要用好啦,除了说算法什么的)

(1)int 是否有符号未知

(2)16位机器和32位机器不同,16位一下开辟16个比特位,32位一下开辟32个比特位

(3)未规定内存从左向右还是右向左分配

(4)容纳位时的一些问题

位段的应用

现了解优化网络传输


二、枚举

枚举里的变量

表示这个类型的变量可能出现的结果

且定义枚举类型时,其每个成员是枚举常量,只能在定义类型时初始化枚举常量的值,在其他地方不能改变(常量嘛)

枚举的格式:

枚举后加分号 " ; " ,如上图花扩后

成员变量之间用逗号相隔,最后成员不用加其他符号

枚举类型相当于整型大小

虽然枚举的常量都能用#define 替换,但是枚举有其细致的优点

枚举的常量相比于#define定义的常量的优点:

(1)可读性和可维护性增强

(2)调试:枚举类型观察到的更细致,而常量在调试中,很多步骤是算好了把结果给我们,我们观察不到具体计算过程

(3)使用方便:枚举变量可一次定义多个,且枚举会自动给成员有序编号(从0开始),而常量很多得亲自定义

(4)枚举有类型,在编译器中会有类型检查,更安全

用法一:枚举和switch结合起来

因为枚举常量是连续或间断连续的常量,和switch语句很搭;枚举的每个成员变量可以取名字,让 case语句 更加明了(可读性增强)


三、联合体

联合体也是一种特殊的自定义类型

联合体的声明与定义

联合体指联合体成员共用同一块内存空间,所以联合体也称为共用体


//联合体类型的声明
union un
{
    char ch;
    int ret;
};

//联合体变量的定义
union un var;

#include <stdio.h>

int main()
{
    printf("%d\n", sizeof(var));    //该联合体变量的大小

    return 0;
}

也发现这与结构体类型的声明定义相似,但联合体是另一种类型,而它与结构体不同的是其内存方式不同

联合体的内存方式

前面了解说联合体是联合体的成员都共用一块内存,具体何意呢,以上面代码定义的联合体为例,见下图

联合体的大小计算

那么联合体的大小如何计算呢?

和结构体类似:

首先,因为成员要共用该块空间,起码要容得下最大的成员,所以联合体大小起码是最大成员的大小

和结构体类似,找到起始大小后考虑总大小为成员最大对其数的倍数,总大小为最大对其数倍数时即为该联合体大小

总结就两步:

(1)找到内存大小最大的成员

(2)让该大小调整为最大对其数的倍数


http://lihuaxi.xjx100.cn/news/663694.html

相关文章

【C++】stack和queue的使用

文章目录Stackstack容器的定义方式:接口函数queuequeue容器的定义方式接口函数栈OJ题目最小栈栈的压入,弹出序列逆波兰表达式求值(后缀表达式)中缀表达式->后缀表达式用两个栈实现队列队列OJ题用队列实现栈使用两个队列实现栈使用一个队列实现栈二叉树的层序遍历I二叉树的层…

juc系列(1)---进程,线程,并行,并发

目录概述进程线程关系并发并行&#xff1a;同步异步&#xff1a;对比概述 进程 程序由指令和数据组成&#xff0c;但这些指令要运行&#xff0c;数据要读写&#xff0c;就必须将指令加载至CPU,数据加载至内 存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载…

机器学习笔记之深度玻尔兹曼机(一)玻尔兹曼机系列整体介绍

机器学习笔记之深度玻尔兹曼机——玻尔兹曼机系列整体介绍引言关于含隐变量模型的对数似然梯度玻尔兹曼机受限玻尔兹曼机深度信念网络深度玻尔兹曼机引言 从本节开始&#xff0c;将介绍玻尔兹曼机系列的最后一个模型——深度玻尔兹曼机(Deep Boltzmann Machine,DBM) 关于含隐…

【数据结构和算法】栈—模拟实现Stack和栈相关算法题

文章目录栈的定义Stack模拟实现相关算法题1.栈的压入弹出序列2.逆波兰表达式(后缀表达式)⭐1.什么是逆波兰表达式?如何转换成逆波兰表达式逆波兰表达式如何计算3.有效的括号总结栈的定义 栈作为一种数据结构&#xff0c;是一种只能在一端进行插入和删除操作的特殊线性表。它按…

机器学习的相关软件框架下载安装

文章目录一、Anaconda1. Anaconda 的下载2. Anaconda 的安装3. Anaconda Navigator 打不开问题&#xff08;不适用所有&#xff09;二、PyTorch-CPU1. PyTorch 环境创建2. PyTorch 下载3. Jupyter 中使用 PyTorch三、Python 版本升级与包的维护1. 更新 Anaconda2. 查看与更新 p…

十五天学会Autodesk Inventor,看完这一系列就够了(一),前言—介绍及区别

众所周知&#xff0c;Autocad是一款用于二维绘图、详细绘制、设计文档和基本三维设计&#xff0c;现已经成为国际上广为流行的绘图工具。Autodesk Inventor软件也是美国AutoDesk公司推出的三维可视化实体模拟软件&#xff0c;有如下两大优势&#xff1a; 1. 使用Autodesk Inve…

Unreal中Interface接口的使用

通过继承Unreal中的接口可以使不同的类有某种共同特性,这里记录一下接口的使用方式。Unreal中的接口分为两种:C接口和蓝图接口,C接口可在蓝图中使用;蓝图中的接口不能直接在C中使用,这里探究一下他们的关系:1.C的接口在C中使用:新建C类,继承UnrealInterface:接口中可以声明虚函…

rocketmq-批量发送消息

参考: https://blog.csdn.net/u010277958/article/details/88647281 https://blog.csdn.net/u010634288/article/details/56049305 https://blog.csdn.net/u014004279/article/details/99644995RocketMQ-批量发送消息 批量发送消息可提高传递小消息的性能。同时也需要满足以下…