【C语言】自定义类型讲解
文章目录
- 一、前言
- 二、结构体
- 2.1 概念
- 2.2 定义
- 2.2.1 通常情况下的定义
- 2.2.2 匿名结构体
- 2.3 结构体的自引用和嵌套
- 2.4 结构体变量的定义与初始化
- 2.5 结构体的内存对齐
- 2.6 结构体传参
- 2.7 结构体实现位段
- 三、枚举
- 3.1 概念
- 3.2 定义
- 3.3 枚举的优点
- 3.3.1 提高代码的可读性
- 3.3.2 防止非法值
- 3.3.3 方便维护
- 3.4 枚举的使用
- 3.4.1 基础使用
- 3.4.2 搭配switch使用
- 3.4.3 使用typedef简化枚举类型
- 四、联合体
- 4.1 概念
- 4.2 定义
- 4.3 联合体的特点
- 4.4 联合体的使用
- 4.4.1 基础使用
- 4.4.2 联合体的内存大小
- 4.5 应用场景
一、前言
本文主要是讲解C语言中的自定义类型,包括:结构体、枚举、联合体。
二、结构体
2.1 概念
在C语言中,结构体是一种强大的数据组织工具,它允许我们将不同类型的数据组合在一起,形成一个逻辑上的整体。通过合理使用结构体,可以提高代码的可读性、可维护性和复用性。
2.2 定义
2.2.1 通常情况下的定义
struct Book
{char name[20];int price;char id[12];
}b1,b2;
2.2.2 匿名结构体
匿名结构体通常用于一些临时性的、不需要多次使用的数据结构。由于没有类型名称,匿名结构体变量只能在声明它的作用域内使用。
struct
{char name[20];int price;char id[12];
}s;
2.3 结构体的自引用和嵌套
结构体可以包含自身类型的成员,这种特性称为自引用。例如,我们可以定义一个链表节点结构体,其中包含一个指向相同结构体类型的指针:
struct Node
{int data;struct Node* next;
};
2.4 结构体变量的定义与初始化
struct Book b1 = {"C Programming", 50, "123456789012"};
这里,b1是一个Book类型的结构体变量,并且在定义时初始化了它的所有成员。如果只初始化部分成员,未初始化的成员将自动初始化为零(对于数值类型)或空字符串(对于字符数组)。
2.5 结构体的内存对齐
在C语言中,结构体的内存布局受到内存对齐规则的影响。内存对齐的目的是提高数据访问的效率。以下是结构体内存对齐的一些基本规则:
- 第一个成员的对齐:结构体的第一个成员放在结构体变量在内存中存储位置的0偏移处开始。
- 后续成员的对齐:从第二个成员往后的所有成员,都放在一个对齐数(成员的大小和默认对齐数的较小值)的整数倍的地址处。
- 结构体总大小的对齐:结构体的总大小是结构体的所有成员的对齐数中最大的那个对齐数的整数倍。
- 嵌套结构体的对齐:如果结构体中嵌套了其他结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。
第二点规则的例子:
struct Example
{char a; // 1字节short b; // 2字节int c; // 4字节char d; // 1字节
};
此时,内存应该如下图对齐:

把成员调换一下
struct Example
{char a; // 1字节int c; // 4字节short b; // 2字节char d; // 1字节
};
如下图:

2.6 结构体传参
在函数调用中,结构体变量可以作为参数传递。由于结构体可能包含多个成员,直接传递结构体变量可能会导致较大的内存拷贝开销。因此,建议在传递结构体时使用指针。例如:
void printBook(struct Book* book)
{printf("Name: %s\n", book->name);printf("Price: %d\n", book->price);printf("ID: %s\n", book->id);
}struct Book b1 = {"C Programming", 50, "123456789012"};
printBook(&b1);
2.7 结构体实现位段
位段是一种特殊的结构体成员,它允许我们指定成员占用的位数。位段通常用于硬件编程或需要精确控制内存布局的场景。例如:
struct S
{char a : 3; // a占3个bitchar b : 4;char c : 5;char d : 4;
};struct S s;
s.a = 7; // 二进制为0111
s.b = 15; // 二进制为1111
在这个例子中,a、b、c和d是位段成员,分别占用3、4、5和4个位。位段的空间是按照需要以4个字节(int)或者一个字节(char)的方式来开辟的。
三、枚举
3.1 概念
在C语言中,枚举(enum)是一种用户自定义的整数类型,它允许为整数值赋予有意义的名称。枚举类型通常用于表示一组相关的常量,使代码更具可读性和易维护性。
3.2 定义
默认是从0开始。
enum 枚举名 {枚举值1,枚举值2,枚举值3,...
};
例如,以下代码定义了一个表示一周七天的枚举类型Day,也可以自定义mon的值,这样它会根据最上面的值往下递增:
enum Day{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun
};
3.3 枚举的优点
3.3.1 提高代码的可读性
枚举类型通过为整数值赋予有意义的名称,使代码更易于理解和维护。例如,使用枚举类型Day时,代码可以写成:
enum Day today = Fri;
3.3.2 防止非法值
枚举类型限制了变量可以取的值,从而防止非法值的赋值。例如,today变量只能取Mon到Sun中的某个值,而不能是其他任意整数。这有助于减少潜在的错误。
3.3.3 方便维护
当需要添加新的枚举值时,只需在枚举定义中添加新的名称,而无需修改其他代码。例如,如果需要添加一个表示“节假日”的枚举值,只需在Day中添加:
enum Day{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun,Holiday
};
3.4 枚举的使用
3.4.1 基础使用
enum Day{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{enum Day today = Mon;printf("today is %d\n", today);return 0;
}
3.4.2 搭配switch使用
enum Day{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun
};int main()
{/*模拟键盘输入 */enum Day today = Mon;switch (today) {case Mon:printf("Today is Monday\n");break;case Tues:printf("Today is Tuesday\n");break;case Wed:printf("Today is Wednesday\n");break;case Thur:printf("Today is Thursday\n");break;case Fri:printf("Today is Friday\n");break;case Sat:printf("Today is Saturday\n");break;case Sun:printf("Today is Sunday\n");break;default:printf("Unknown day\n");}return 0;
}
3.4.3 使用typedef简化枚举类型
typedef enum Day{Mon = 1,Tues,Wed,Thur,Fri,Sat,Sun
}Day_t;int main()
{/*模拟键盘输入 */Day_t today = Sat;switch (today) {case Mon:printf("Today is Monday\n");break;case Tues:printf("Today is Tuesday\n");break;case Wed:printf("Today is Wednesday\n");break;case Thur:printf("Today is Thursday\n");break;case Fri:printf("Today is Friday\n");break;case Sat:printf("Today is Saturday\n");break;case Sun:printf("Today is Sunday\n");break;default:printf("Unknown day\n");}return 0;
}
四、联合体
4.1 概念
在C语言中,联合体也叫共用体,联合体(Union)是一种特殊的数据结构,它允许在同一内存位置上存储不同类型的变量。换句话说,联合体中的所有成员都共享同一块内存空间,因此,联合体的大小是它最大成员所需的内存空间。联合体是一种有效的内存使用方式,尤其是在我们需要在不同时间点使用不同类型的数据时。
4.2 定义
在C语言中,联合体的定义使用关键字 union。与结构体不同,结构体中的每个成员都有自己的内存空间,而联合体中的所有成员共用同一块内存。其基本定义格式如下:
union Un {char c;int i;
};
在上述代码中,Un 是联合体的名字,c 和 i 是该联合体的成员。虽然它有两个成员,一个是字符型 char,另一个是整型 int,但是这两个成员是共享内存的。也就是说,它们存储的数据会覆盖彼此。
4.3 联合体的特点
- 共用内存:联合体的成员共享同一块内存,所有成员的起始地址相同。因此,每次只能存储一个成员的数据。修改一个成员的值会影响其他成员,因为它们共用同一块内存。
- 大小:联合体的大小由其最大成员的大小决定。即使联合体中有多个成员,它的大小将是最大的成员所占内存的大小。举个例子,在上述定义中,char 通常占 1 字节,int 通常占 4 字节,因此该联合体的大小通常是 4 字节(由 int 决定)。
- 内存优化:联合体提供了内存优化的功能,尤其适用于当某个变量需要存储不同类型的数据,但在同一时刻只需要存储其中一个数据时。例如,保存一个变量可能是整数,也可能是字符值,根据需要使用不同类型的数据时,使用联合体可以节省内存空间。
4.4 联合体的使用
4.4.1 基础使用
union Un
{char c;int i;
};int main()
{union Un u;u.c = 'A';u.i = 100;printf("c=%c i=%d\n", u.c, u.i);return 0;
}
此时,c=d i=100。
分析一下代码执行过程,首先u.c = ‘A’;此时联合体的内存内容是0x41。然后,u.i = 100;假设此时是小端模式则内存的内容是0x64。联合体是共享内存的所以u.c的内容已经被覆盖掉,char类型是一个字节,所以此时这个字节里面的内容用十进制表示就是100用ascii值表示就是d。
4.4.2 联合体的内存大小
#include <stdio.h>union Un {char c;int i;
};int main()
{union Un u;printf("Size of union Un: %zu bytes\n", sizeof(u));return 0;
}
根据上述代码,输出的联合体大小通常为 4 字节(这取决于系统架构)。这是因为 int 类型通常占 4 字节,而 char 占 1 字节。由于联合体共享内存,所以联合体的大小是最大成员(int 类型)所占的字节数。
4.5 应用场景
- 节省内存:当我们需要存储多种数据类型,但在某一时刻只需要其中之一时,使用联合体可以有效节省内存。例如,在编写操作系统或硬件驱动时,联合体常用于存储可能是不同类型的寄存器值。
- 类型转换:在一些需要类型转换的场合,联合体常被用作一种简便的方式来查看和修改不同数据类型的内存表示。例如,可以用联合体来将一个 float 类型的值解释为 int 类型的位表示,反之亦然。
#include <stdio.h>union Converter {float f;int i;
};int main()
{union Converter c;// 将 float 类型的值存储在联合体中c.f = 3.14f;// 打印 float 类型的值printf("Float value: %f\n", c.f);// 打印相应的 int 类型位表示printf("Int representation (as bits): %d\n", c.i);// 将 int 类型值赋给联合体的 i 成员c.i = 1078523331; // 通过 int 位表示修改 float 值// 打印修改后的 float 值printf("Modified float value: %f\n", c.f);return 0;
}
相关文章:
【C语言】自定义类型讲解
文章目录 一、前言二、结构体2.1 概念2.2 定义2.2.1 通常情况下的定义2.2.2 匿名结构体 2.3 结构体的自引用和嵌套2.4 结构体变量的定义与初始化2.5 结构体的内存对齐2.6 结构体传参2.7 结构体实现位段 三、枚举3.1 概念3.2 定义3.3 枚举的优点3.3.1 提高代码的可读性3.3.2 防止…...
Day25 洛谷 提高- 1007
零基础洛谷刷题记录 Day01 2024.11.18 Day02 2024.11.25 Day03 2024.11.26 Day04 2024.11.28 Day05 2024.11.29 Day06 2024 12.02 Day07 2024.12.03 Day08 2024 12 05 Day09 2024.12.07 Day10 2024.12.09 Day11 2024.12.10 Day12 2024.12.12 Day13 2024.12.16 Day14 2024.12.1…...
LabVIEW涡轮诊断系统
一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备,其运行状态直接关系到生产安全与经济效益。据统计,涡轮故障导致的非计划停机可造成每小时数十万元的经济损失,且突发故障可能引发严重安全事故。传统人…...
GGML、GGUF、GPTQ 都是啥?
GGML、GGUF和GPTQ是三种与大型语言模型(LLM)量化和优化相关的技术和格式。它们各自有不同的特点和应用场景,下面将详细解释: 1. GGML(GPT-Generated Model Language) 定义:GGML是一种专为机器学习设计的张量库,由Georgi Gerganov创建。它最初的目标是通过单一文件格式…...
Kafka 使用说明(kafka官方文档中文)
文章来源:kafka -- 南京筱麦软件有限公司 第 1 步:获取 KAFKA 下载最新的 Kafka 版本并提取它: $ tar -xzf kafka_{{scalaVersion}}-{{fullDotVersion}}.tgz $ cd kafka_{{scalaVersion}}-{{fullDotVersion}} 第 2 步:启动 KAFKA 环境 注意:您的本地环境必须安装 Java 8+。…...
Kubernetes 中 BGP 与二层网络的较量:究竟孰轻孰重?
如果你曾搭建过Kubernetes集群,就会知道网络配置是一个很容易让人深陷其中的领域。在负载均衡器、服务通告和IP管理之间,你要同时应对许多变动的因素。对于许多配置而言,使用二层(L2)网络就完全能满足需求。但边界网关…...
大模型综述一镜到底(全文八万字) ——《Large Language Models: A Survey》
论文链接:https://arxiv.org/abs/2402.06196 摘要:自2022年11月ChatGPT发布以来,大语言模型(LLMs)因其在广泛的自然语言任务上的强大性能而备受关注。正如缩放定律所预测的那样,大语言模型通过在大量文本数…...
物理群晖SA6400核显直通win10虚拟机(VMM)
写在前面:请先确保你的核显驱动支持开启SR-IOV 确保你的BIOS开启了以下选项: VT-D VMX IOMMU Above 4G ResizeBAR 自行通过以下命令确认支持情况: dmesg | grep -i iommudmesg | grep DMAR分配1个虚拟vGPU:echo 1 | sudo tee /sy…...
【python】tkinter实现音乐播放器(源码+音频文件)【独一无二】
👉博__主👈:米码收割机 👉技__能👈:C/Python语言 👉专__注👈:专注主流机器人、人工智能等相关领域的开发、测试技术。 【python】tkinter实现音乐播放器(源码…...
ESP32开发工具介绍:Thonny——初学者的MicroPython利器
文章目录 引言什么是 Thonny?为什么选择 Thonny 开发 ESP32?1. **MicroPython 的天然支持**2. **极简的配置流程**3. **适合快速原型开发**如何用 Thonny 开发 ESP32?步骤 1:准备工作步骤 2:烧录 MicroPython 固件步骤 3:在 Thonny 中连接 ESP32步骤 4:编写并运行代码Th…...
进程的环境变量
export MUDUO_LOG_DEBUG1 ./testif (::getenv("MUDUO_LOG_TRACE"))return true;有时在程序运行前,我们希望设置环境变量。此处::表示全局命名空间。 在类 Unix 系统(如 Linux、macOS)中,环境变量并不直接存储在堆、栈或…...
Qwen2.5-Max:AI技术的新里程碑
随着人工智能(AI)技术的不断进步,全球各大科技公司都在竞相推出更强大的语言模型。近日,阿里巴巴发布了其最新的超大规模混合专家模型(MoE)——Qwen2.5-Max,这一成果不仅在多个基准测试中超越了…...
MyBatis-Plus速成指南:常用注解
Table Name: 概述: MyBatis-Plus 在确定操作的表时,由 BaseMapper的泛型决定,即实体类决定,且默认操作的表名和实体类的类名一致 问题: 如果实体类类型的类名和要操作表的表名不一致会出现什么问题?(把 us…...
Vue.js组件开发-Vue实现上传word模版打印设置自定义样式和布局
要使用 Vue 实现上传 Word 模板、打印并设置自定义样式和布局,可以借助一些工具和库来完成这个任务。 实现步骤 创建 Vue 项目:使用 Vue CLI 创建一个新的 Vue 项目。安装依赖:安装 docx-templates 库来处理 Word 模板,file-sav…...
Linux 压缩打包
Linux压缩打包 文章目录 Linux压缩打包压缩的意义和原理压缩的意义压缩的原理压缩与解压缩的好处 压缩打包命令.zipzip 命令用法unzip 的用法 .gzgzip 的用法gunzip 的用法 .bz2bzip2 的用法bunzip2 的用法 .xzxz 命令用法 tar 04-Linux压缩打包课后习题 压缩的意义和原理 压缩…...
RabbitMQ深度探索:前置知识
消息中间件: 消息中间件基于队列模式实现异步 / 同步传输数据作用:可以实现支撑高并发、异步解耦、流量削峰、降低耦合 传统的 HTTP 请求存在的缺点: HTTP 请求基于响应的模型,在高并发的情况下,客户端发送大量的请求…...
29.日常算法
1. 验证回文串 II 题目来源 给定一个非空字符串 s,请判断如果 最多 从字符串中删除一个字符能否得到一个回文字符串。 示例 1: 输入: s “aba” 输出: true 示例 2: 输入: s “abca” 输出: true 解释: 可以删除 “c” 字符 或者 “b” …...
智慧校园平台:构建现代化教育体系的技术支撑
在当今信息技术飞速发展的时代,智慧校园平台成为了现代教育领域中的重要组成部分。智慧校园平台不仅能够提升学校的管理水平,还能提供更为个性化和高效的教学服务,从而促进学生的全面发展。 数据分析是智慧校园平台的重要组成部分。通过对学生…...
【单层神经网络】基于MXNet的线性回归实现(底层实现)
写在前面 刚开始先从普通的寻优算法开始,熟悉一下学习训练过程下面将使用梯度下降法寻优,但这大概只能是局部最优,它并不是一个十分优秀的寻优算法 整体流程 生成训练数据集(实际工程中,需要从实际对象身上采集数据…...
20250204将Ubuntu22.04的默认Dash的shell脚本更换为bash
20250204将Ubuntu22.04的默认Dash的shell脚本更换为bash 2025/2/4 23:45 百度:dash bash https://blog.csdn.net/2201_75772333/article/details/136955776 【Linux基础】dash和bash简介 Dash(Debian Almquist Shell)和 Bash(Bou…...
Golang 并发机制-3:通道(channels)机制详解
并发编程是一种创建性能优化且响应迅速的软件的强大方法。Golang(也称为 Go)通过通道(channels)这一特性,能够可靠且优雅地实现并发通信。本文将揭示通道的概念,解释其在并发编程中的作用,并提供…...
Python处理数据库:MySQL与SQLite详解
Python处理数据库:MySQL与SQLite详解 在数据处理和存储方面,数据库扮演着至关重要的角色。Python提供了多种与数据库交互的方式,其中pymysql库用于连接和操作MySQL数据库,而SQLite则是一种轻量级的嵌入式数据库,Pytho…...
可视化大屏在石油方面的应用。
可视化大屏通过整合石油工业全链条数据,构建数字孪生驱动的运营监控体系,显著提升油气勘探、开采、储运及炼化的管理效能。其技术架构依托工业物联网(IIoT)实时采集钻井参数、管道压力、储罐液位等数据,通过OPC UA协议…...
【学术投稿-2025年计算机视觉研究进展与应用国际学术会议 (ACVRA 2025)】从计算机基础到HTML开发:Web开发的第一步
会议官网:www.acvra.org 简介 2025年计算机视觉研究进展与应用(ACVRA 2025)将于2025年2月28-3月2日在中国广州召开,将汇聚世界各地的顶尖学者、研究人员和行业专家,聚焦计算机视觉领域的最新研究动态与应用成就。本次…...
【 AI agents】letta:2024年代理堆栈演进(中英文翻译)
The AI agents stack AI 代理堆栈 November 14, 2024 11月 14, 2024原文: The AI agents stack官方教程教程学习笔记: 【memgpt】letta 课程1/2:从头实现一个自我编辑、记忆和多步骤推理的代理Understanding the AI agents landscape 了解 AI 代理环境 Although we see a …...
Axure PR 9 旋转效果 设计交互
大家好,我是大明同学。 这期内容,我们将学习Axure中的旋转效果设计与交互技巧。 旋转 创建旋转效果所需的元件 1.打开一个新的 RP 文件并在画布上打开 Page 1。 2.在元件库中拖出一个按钮元件。 创建交互 创建按钮交互状态 1.选中按钮元件…...
Docker 部署教程jenkins
Docker 部署 jenkins 教程 Jenkins 官方网站 Jenkins 是一个开源的自动化服务器,主要用于持续集成(CI)和持续交付(CD)过程。它帮助开发人员自动化构建、测试和部署应用程序,显著提高软件开发的效率和质量…...
二、CSS笔记
(一)css概述 1、定义 CSS是Cascading Style Sheets的简称,中文称为层叠样式表,用来控制网页数据的表现,可以使网页的表现与数据内容分离。 2、要点 怎么找到标签怎么操作标签对象(element) 3、css的四种引入方式 3.1 行内式 在标签的style属性中设定CSS样式。这种方…...
计算图 Compute Graph 和自动求导 Autograd | PyTorch 深度学习实战
前一篇文章,Tensor 基本操作5 device 管理,使用 GPU 设备 | PyTorch 深度学习实战 本系列文章 GitHub Repo: https://github.com/hailiang-wang/pytorch-get-started PyTorch 计算图和 Autograd 微积分之于机器学习Computational Graphs 计算图Autograd…...
基于 Java 开发的 MongoDB 企业级应用全解析
基于Java的MongoDB企业级应用开发实战 目录 背景与历史MongoDB的核心功能与特性企业级业务场景分析MongoDB的优缺点剖析开发环境搭建 5.1 JDK安装与配置5.2 MongoDB安装与集群配置5.3 开发工具选型 Java与MongoDB集成实战 6.1 项目依赖与驱动选择6.2 连接池与客户端配置6.3…...
