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

【C语言】自定义数据类型——结构体

目录一、引入结构体二、结构体的定义、创建与初始化1.定义2.创建①定义后直接创建②先定义再创建③使用匿名结构体不推荐因为无法再次使用该类型④创建结构体数组3.初始化①按成员顺序初始化②按照任意顺序初始化③先创建再逐个赋值三、结构体成员的访问1.使用.访问2.使用-访问3.结构体成员嵌套的访问四、结构体作为参数传递1.传值2.传地址五、typedef简化结构体六、结构体的自引用七、结构体内存对齐问题节省时间1.什么是内存对齐2.需要使用内存对齐的原因3.内存对齐的规则4.举例5.小结6.控制对齐方式八、结构体实现位段操作节省空间1.位域简介与使用原因2.位域的定义与使用时的注意事项3.举例4.工程应用一、引入结构体C语言已经给我们提供了不少内置数据类型例如 int、char、float 等但是如果我们需要描述由姓名、年龄、性别、身高、体重等等等等多种数据类型复合而成的“人”这样一个对象时在C语言中找不到现成的这样的数据类型。但是C语言给我们提供了创造数据类型的东西——结构体结构体struct是C语言中一种非常重要的用户自定义数据类型它允许我们将不同类型的数据组合在一起形成一个逻辑上的整体。这对于表示复杂对象如学生、汽车、坐标点等非常方便。二、结构体的定义、创建与初始化1.定义使用struct关键字来定义结构体。定义结构体时需要列出其包含的成员member每个成员可以是任意基本数据类型、数组、指针甚至其他结构体。/******************************* 语法 *******************************/ struct 结构体标签 { 类型 成员1; 类型 成员2; ... }; // 分号不能省略 /******************************* 示例 *******************************/ struct Student { int id; // 学号 char name[50]; // 姓名 float score; // 成绩 }; //这里 Student 是结构体标签tag它本身不是变量名而是一种新的数据类型。2.创建定义好结构体后就可以用它来创建变量了。有三种方式①定义后直接创建struct Student { int id; char name[50]; float score; } stu1, stu2; // 在定义类型后直接创建变量②先定义再创建struct Student { int id; // 学号 char name[50]; // 姓名 float score; // 成绩 }; int main() { struct Student stu1, stu2; // 创建了两个Student类型的变量 return 0; }③使用匿名结构体不推荐因为无法再次使用该类型struct { int id; char name[50]; float score; } stu1, stu2; // struct后面没有标签后续的程序只能使用stu1和stu2这两个数据④创建结构体数组结构体数组用于存储多个相同类型的结构体对象struct Student { int id; // 学号 char name[50]; // 姓名 float score; // 成绩 }; int main() { //创建结构体数组数组的变量类型是结构体类型有三个成员变量每个变量都是一个结构体类型 struct Student class[3] { {1001, 张三, 88.5}, {1002, 李四, 92.0}, {1003, 王五, 76.5} }; //数组元素的访问 for (int i 0; i 3; i) { printf(%d\t%s\t%.1f\n, class[i].id, class[i].name, class[i].score); } return 0; }3.初始化未显式初始化的成员会被自动赋值为 0对于数值类型或空字符串对于字符数组初始化可以在创建变量时进行有多种初始化方法①按成员顺序初始化注意必须按照结构体定义中成员的顺序依次给出初始值且值的类型要匹配。struct Student stu1 {1001, 张三, 88.5};②按照任意顺序初始化可以按照任意顺序初始化使用.成员名来指定。struct Student stu2 {.name 李四, .id 1002, .score 92.0};③先创建再逐个赋值struct Student stu3; stu3.id 1003; strcpy(stu3.name, 王五); // 注意不能直接用 给数组赋值 stu3.score 76.5;三、结构体成员的访问1.使用.访问printf(学号%d\n, stu1.id); printf(姓名%s\n, stu1.name); printf(成绩%.1f\n, stu1.score);2.使用-访问如果使用指向结构体的指针则需要用箭头运算符-来访问成员或者先解引用再用点号。struct Student *p stu1; printf(学号%d\n, p-id); // 等价于 (*p).id3.结构体成员嵌套的访问struct Date { int year; int month; int day; }; struct Student { int id; char name[50]; float score; struct Date birthday; // 嵌套结构体 }; int main() { struct Student stu {1001, 张三, 88.5, {2000, 5, 20}}; printf(生日%d年%d月%d日\n, stu.birthday.year, stu.birthday.month, stu.birthday.day); return 0; }四、结构体作为参数传递1.传值将整个结构体作为参数传递函数会得到一份拷贝修改拷贝不影响原结构体。使用 . 进行成员访问缺点如果结构体很大拷贝开销大。void printStudent(struct Student s) { printf(%d %s %.1f\n, s.id, s.name, s.score); } // 调用printStudent(stu);2.传地址传递结构体指针函数内通过指针访问原始数据避免拷贝且能修改原结构体。使用 - 进行成员访问推荐使用指针尤其是结构体较大时。函数传参的时候参数是需要压栈会有时间和空间上的系统开销。 如果传递⼀个结构体对象的时候结构体过大参数压栈的系统开销比较大所以会导致性能的下降。void modifyScore(struct Student *s, float newScore) { printf(%d %s %.1f\n, s-id, s-name, s-score); s-score newScore; // 直接修改原变量 } // 调用modifyScore(stu, 99.0);五、typedef简化结构体使用typedef可以为结构体定义一个别名这样在声明变量时就不必每次都写struct关键字。/***************************************** 第一种 *****************************************/ typedef struct Student { int id; char name[50]; float score; } Stu; // Stu 现在是 struct Student 的别名 /***************************************** 第二种 *****************************************/ /* 或者使用匿名结构体在定义时直接使用typedef */ typedef struct { int id; char name[50]; float score; } Stu; // 匿名结构体直接定义别名Student int main() { Stu stu1, stu2; return 0; }六、结构体的自引用/*************************** 错误的自引用 ***************************/ struct Node { int data; struct Node next; }; //⼀个结构体中再包含⼀个同类型的结构体变量这样结构体变量的大小将是无穷大 /*************************** 正确的自引用 ***************************/ struct Node { int data; struct Node* next; };/*************************** 错误的自引用 ***************************/ typedef struct { int data; Node* next; //虽然使用typedef重命名但是内部成员变量还没有接收到 }Node; /*************************** 正确的自引用 ***************************/ typedef struct Node { int data; struct Node* next; }Node;七、结构体内存对齐问题节省时间1.什么是内存对齐内存对齐Memory Alignment是指编译器将结构体的每个成员放置在内存中特定位置的过程以提高CPU访问内存的效率。它会在成员之间插入“填充字节”padding使得每个成员的起始地址满足一定的对齐要求。2.需要使用内存对齐的原因硬件要求许多CPU架构如RISC、x86要求特定类型的数据必须存放在特定地址上否则会引发硬件异常如总线错误或性能急剧下降。例如32位CPU通常要求int类型的数据地址是4的倍数。访问效率即使某些CPU允许非对齐访问如x86但访问对齐的数据通常更快可能一次内存访问即可完成而非对齐可能需要两次内存访问并拼接数据。原子性保证对齐的数据可以保证原子操作在某些平台上非对齐可能导致操作被拆分。3.内存对齐的规则确定起点结构体的第一个成员对齐到和结构体变量起始位置偏移量为0的地址处确定其他成员对齐位置其他成员变量要对齐到对齐数的整数倍的地址处对齐数编译器默认的⼀个对齐数与该成员变量大小的较小值。VS 编辑器中默认的对齐数为 8Linux中gcc没有默认对齐数对齐数就是成员自身的大小确定总大小结构体总大小为最大对齐数结构体中每个成员变量都有一个对齐数所有对齐数中最大的的整数倍嵌套问题如果嵌套了结构体的情况嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处结构体的整体大小就是所有最大对齐数含嵌套结构体中成员的对齐数的整数倍。4.举例5.小结在设计结构体的时候我们既要满足对齐又要节省空间那么就要让占用空间小的成员尽量集中在⼀起6.控制对齐方式在某些场景如网络协议、硬件寄存器、文件格式我们希望结构体紧密排列不插入填充字节。这时可以使用编译器扩展来“取消”对齐#pragma pack(x) struct PackedExample { char c; int i; short s; }; #pragma pack()八、结构体实现位段操作节省空间1.位域简介与使用原因位域允许我们将结构体成员按位bit分配空间适用于需要精确控制位数、节省内存的场景如硬件寄存器、网络协议头等2.位域的定义与使用时的注意事项定义在成员后加冒号和位数struct Flags { unsigned int a : 1; // a 占1位 unsigned int b : 2; // b 占2位 unsigned int c : 3; // c 占3位 };注意事项位域成员必须是无符号或有符号整数类型int、unsigned int等。不能对位域成员取地址。struct A { int _b : 5; int _c : 10; int _d : 30; }; int main() { struct A sa {0}; //错误示范 scanf(%d, sa._b); //正确的示范​ int b 0; scanf(%d, b); sa._b b; return 0; }位域的总位数不能超过底层类型的位数通常为unsigned int的位数如32位。位段中的成员在内存中从左向右分配还是从右向左分配标准尚未定义。当一个结构包含两个位段第二个位段成员比较大无法容纳于第一个位段剩余的位时是舍弃剩余的位还是利用标准尚未定义。3.举例4.工程应用网络协议中IP数据报的格式我们可以看到其中很多的属性只需要几个bit位就能描述这里使用位段能够实现想要的效果也节省了空间这样网络传输的数据报大小也会较小一些对网络的畅通是有帮助的。

相关文章:

【C语言】自定义数据类型——结构体

目录 一、引入结构体 二、结构体的定义、创建与初始化 1.定义 2.创建 ①定义后直接创建 ②先定义再创建 ③使用匿名结构体(不推荐,因为无法再次使用该类型) ④创建结构体数组 3.初始化 ①按成员顺序初始化 ②按照任意顺序初始化 …...

【无限视距】:R3nzSkin的MOBA视野增强技术原理与实战指南

【无限视距】:R3nzSkin的MOBA视野增强技术原理与实战指南 【免费下载链接】R3nzSkin Skin changer for League of Legends (LOL) 项目地址: https://gitcode.com/gh_mirrors/r3n/R3nzSkin 在MOBA游戏的对抗中,视野控制往往决定战局走向。R3nzSkin…...

5分钟搞定PySide2串口助手:从QT Designer到Python打包全流程

5分钟打造PySide2串口助手:从UI设计到跨平台部署的极速开发指南 1. 开发环境配置与工具链搭建 对于嵌入式开发者和物联网爱好者而言,快速构建一个功能完善的串口调试工具是硬件调试的刚需。PySide2作为Qt官方维护的Python绑定库,结合Python的…...

快速了解智能体

1.了解智能体 这个时代,AI开始已经深入到我们生活中了,智能体的概念也慢慢出现在我们的视野中了。这两个概念并不完全一样。AI 是模拟人类智能的技术领域与能力集合,智能体是依托 AI 实现自主感知、决策、 行动的目标驱动实体,后者…...

游戏模组框架:SMAPI构建个性化星露谷体验的全栈解决方案

游戏模组框架:SMAPI构建个性化星露谷体验的全栈解决方案 【免费下载链接】SMAPI The modding API for Stardew Valley. 项目地址: https://gitcode.com/gh_mirrors/smap/SMAPI 1 技术架构解析:SMAPI如何重塑游戏扩展能力 在独立游戏模组生态中&a…...

深度学习_YOLO,卡尔曼滤波和

1.YOLO 1.1 简介 YOLO系列算法是一类典型的one-stage目标检测算法,其利用anchor box将分类与目标定位的回归问题结合起来,从而做到了高效、灵活和泛化性能好,所以在工业界也十分受欢迎. Yolo算法采用一个单独的CNN模型实现end-to-end的目标检…...

EF Core 10向量搜索扩展已进入GA倒计时:2026 Q2前必须完成的3项架构升级(含迁移路径图、兼容性矩阵与SQL Server 2022 CU23关键补丁号)

第一章:EF Core 10向量搜索扩展GA倒计时全景洞察随着 .NET 9 和 EF Core 10 的正式发布临近,官方宣布的 EF Core Vector Search Extensions(向量搜索扩展)已进入 GA(General Availability)前最后验证阶段。…...

TwinCAT3实战指南:PLC变量与硬件IO的高效绑定技巧

1. TwinCAT3环境搭建与基础概念 第一次接触TwinCAT3的工程师常常会被各种专业术语搞得晕头转向。其实可以把TwinCAT3想象成一个"翻译官",它负责把PLC程序中的变量指令"翻译"成硬件能听懂的电信号。我刚开始使用时,最头疼的就是变量定…...

位置编码详解

位置编码(Positional Encoding, PE) 是自然语言处理(NLP)中,特别是 Transformer 模型架构里的一个核心概念。它的作用是给序列中的每个词(Token)注入“顺序”或“位置”信息。一、WHY&#xff1…...

为什么你的PHP 8.9 JIT提速仅3.2%?揭秘CPU微架构适配盲区(Intel Ice Lake vs AMD Zen3实测对比)

第一章:PHP 8.9 JIT 编译器生产环境落地步骤PHP 8.9 并非官方已发布的版本(截至 2024 年,PHP 最新稳定版为 8.3),但本节基于社区实验性构建的 PHP 8.9-alpha 分支(含增强型 LLVM 后端 JIT 和运行时配置热重…...

IndexTTS-2-LLM功能全解析:不仅能用,还这么好用!

IndexTTS-2-LLM功能全解析:不仅能用,还这么好用! 1. 引言:为什么选择IndexTTS-2-LLM? 想象一下,你正在制作一个有声读物,需要把大量文字转换成自然流畅的语音。传统语音合成工具生成的机械音让…...

计算机考研 408 数据结构 排序算法

时间复杂度 or交换次数空间复杂度移动次数稳定最好最坏直接插入排序O(n)O()O(1)O()√冒泡排序O(n)O()O(1)O()√简单选择排序O()O()O(1)O(n)希尔排序O(1)O()快速排序O(nlogn)O()O(logn) 栈平均 O(nlogn)最坏 O()堆排序O(nlogn)O(nlogn)O(1)O(nlogn)二路归并排序O(nlogn)O(nlogn)…...

老年关怀:AI Agent作为健康与生活伴侣

老年关怀:AI Agent作为健康与生活伴侣 1. 核心概念 1.1 老年健康与生活关怀的“黄金三角困境” 核心概念拆解 老年健康与生活关怀的黄金三角困境是我在过去7年参与5个省级智慧养老试点项目、调研超过3000位独居/空巢老人、200家社区养老机构和100家科技厂商后总结出的核心矛…...

AI Agent在物流与运输中的应用:路径优化与调度自动化

AI Agent在物流与运输中的应用:路径优化与调度自动化 引言 在当今快速发展的商业环境中,物流与运输行业正面临着前所未有的挑战。随着电子商务的爆发式增长,消费者对配送速度、成本和可靠性的要求越来越高。同时,全球化供应链的复杂性、燃油价格的波动以及环保法规的日益…...

易语言开发雷电模拟器中控系统源码包|完整框架+核心模块源代码

温馨提示:文末有联系方式易语言雷电模拟器中控系统源码发布 本套为基于易语言开发的雷电模拟器中控框架完整源码包,涵盖主控逻辑、设备通信、指令调度等核心模块,采用模块化设计,便于二次开发与功能扩展。框架完整性说明 当前版本…...

洛谷题解:P15804 [GESP202603 八级] 消息查找

考场上的代码赛后发现改五十个字符就过了,呜呜呜。 题意 给一个图,每个节点指向上一个节点,有最多 100010001000 条附加边,从一个大编号的点指向小编号,快速求任意两点的距离。 思路 由于指向上一个节点的边太浪费…...

我让 Claude 和 Codex 同时审计 个模块,它们只在 个上达成共识识

整体排查思路 我们的目标是验证以下三个环节是否正常: 登录成功时:服务器是否正确生成了Session并返回了包含正确 JSESSIONID的Cookie给浏览器。 浏览器端:浏览器是否成功接收并存储了该Cookie。 后续请求:浏览器在执行查询等操作…...

Shell应用手册(一) 5 .终端连接与环境配置(SSH连接、命令行提示符含义)

对于后端开发者、运维工程师而言,终端是日常工作中最常用的工具之一。无论是远程管理服务器,还是本地调试程序,终端连接的稳定性、环境配置的合理性,直接影响工作效率。而SSH连接作为远程终端访问的核心方式,命令行提示…...

springboot基于Hadoop的健康饮食推荐系统的设计与实现_5578bn9k_yh025

前言 随着人们生活水平的提高和健康意识的增强,越来越多的人开始关注自己的饮食习惯和健康状况。然而,传统饮食推荐方式往往缺乏个性化与数据支撑,难以满足用户多样化需求。SpringBoot基于Hadoop的健康饮食推荐系统应运而生,旨在为…...

基于扩展卡尔曼滤波EKF和模型预测控制MPC,自动泊车场景建模开发,文复现。 MATLAB(工...

基于扩展卡尔曼滤波EKF和模型预测控制MPC,自动泊车场景建模开发,文复现。 MATLAB(工程项目线上支持)自动泊车这活儿看着简单,实际操作起来全是坑。今天咱们就掰开揉碎了聊聊怎么用EKF和MPC这对黄金搭档搞定车位里的毫米…...

图片格式转换效率革命:从繁琐流程到一键操作的技术突破

图片格式转换效率革命:从繁琐流程到一键操作的技术突破 【免费下载链接】Save-Image-as-Type Save Image as Type is an chrome extension which add Save as PNG / JPG / WebP to the context menu of image. 项目地址: https://gitcode.com/gh_mirrors/sa/Save-…...

qtCreator应用程序输出窗口qDebug不输出问题

可以通过配置环境变量export QT_LOGGING_RULES"*.debugtrue;qt.*.debugfalse"...

YOLO 系列专栏(三十七)【全网首发】YOLO26 独家卷积改进|CVPR 2025 FDConv 频率动态卷积,结合 FDC3k2 二次创新,突破小目标特征表达瓶颈

目录 摘要 一、引言:传统卷积的小目标痛点 二、核心技术原理解析 2.1 FDConv 频率动态卷积(CVPR 2025 核心思想) 2.1.1 核心流程 2.1.2 关键优势 2.2 FDC3k2 二次创新模块(全网首发) 2.2.1 结构设计 2.3 FDConv vs 传统卷积/主流动态卷积(小目标场景对比) 三、…...

BLE 协议栈:HCI ISO 数据详解

BLE 协议栈:HCI ISO 数据详解前言一、定义1、HCI ISO 数据包(ISO Data Packet)二、ISO 数据包结构1、Host to Controller 格式2、Controller to Host 格式3、字节级格式表三、ISO Data Load 格式1、Host to Controller(主机到控制…...

高薪招聘!13-40K!AI大模型应用工程师,带你玩转AI前沿技术!

本文介绍了一则AI大模型应用工程师的招聘信息,岗位职责包括AI大模型在实际业务场景中的应用开发、需求分析、模型应用场景设计、智能应用构建与优化等。要求应聘者具备计算机相关专业学历,熟练掌握Python,有Java项目开发经验者优先&#xff1…...

Linux:入门开发工具--Git和GDB调试器

1.版本控制器Git1.1 Git的背景知识Git 是一款由 Linux 创始人 Linus Torvalds 在 2005 年开发的分布式版本控制系统。当时 Linux 内核社区因商业版本控制工具授权问题被迫更换工具,急需一个高效、分布式、速度极快的管理方案,Git 因此诞生,它…...

大模型之Linux服务器部署大模型斜

一、各自优势和对比 这是检索出来的数据,据说是根据第三方评测与企业数据,三款产品在代码生成质量上各有侧重: 产品 语言优势 场景亮点 核心差异 百度 Comate C核心代码质量第一;Python首生成率达92.3% SQL生成准确率提升35%&…...

【Agent面试题大揭秘】50道高频题深度解析,助你拿下Offer!

一、Agent 基础与架构什么是 Agent 的“感知-规划-行动”闭环?如何实现?Agent 的长期记忆和短期记忆分别如何设计和存储?如何解决 Agent 的“幻觉”问题?Agent 的状态管理是如何实现的?如何保证多轮对话的状态一致性&a…...

Windows系统的MBR磁盘分区

对于逻辑类数据恢复技术的学习,最重要的就是对各种系统下的分区结构及文件系统结构的学习。作为目前主流的操作系统Windows,它能够支持的分区结构包括MBR磁盘分区、动态磁盘分区及GPT磁盘分区:它能够支持的文件系统结构包括FAT12、FAT16、FAT…...

数学建模算法案例精讲500篇-【自动驾驶】自动驾驶中的决策规划算法概述(代码篇第一篇:全局路径规划+行为决策)

目录 一、前言:代码篇核心定位与环境说明 1.1 运行环境说明 1.2 代码设计思路 二、A*算法代码实现(全局路径规划主流) 2.1 算法核心回顾(对应理论篇2.2节) 2.2 完整MATLAB代码实现 2.3 代码说明与调试技巧 2.3.1 代码结构对应理论 2.3.2 调试技巧(工程适配重点)…...