C语言——结构体
一、结构体的创建
1、定义
在 C 语言中,结构体是一种自定义的数据类型,它允许将不同类型的数据项组合成一个单一实体。这在组织复杂数据时非常有用,因为它可以将有逻辑关系的数据组合在一起。结构体是一些值的集合,这些值是结构成员变量。
2、结构体的声明格式
结构体定义由关键字 struct 和结构体名组成,结构体名可以根据需要自行定义。
struct tag {member-listmember-listmember-list ...
} variable-list ;struct 结构体标签
{变量定义;变量定义;变量定义;...
} 结构变量;
tag 是结构体标签。
member-list 是标准的变量定义,比如 int i; 或者 float f;,或者其他有效的变量定义。
variable-list 结构变量,定义在结构的末尾,最后一个分号之前,您可以指定一个或多个结构变量。
在一般情况下,tag、member-list、variable-list 这 3 部分至少要出现 2 个。
3、结构体的声明实例
(1)没有具体标签(匿名)
//此声明声明了拥有3个成员的结构体,分别为int类型的a,char类型的的b和double类型的c//同时又声明了结构体变量s1//这个结构体并没有标明其标签struct{int a;char b;double c;} s1;
(2)有具体标签
//此声明声明了拥有3个成员的结构体//结构体的标签被命名为Student,没有声明变量struct Student{int age;char name[20];int height;};
(3)同时声明变量
//此声明声明了拥有3个成员的结构体//结构体的标签被命名为Person,同时声明变量struct Person{int age;char name[20];int height;};
在上面的声明中,第二个和第三个声明被编译器当作两个完全不同的类型,即使他们的成员列表是一样的。因为它们的标签名不一样,即使两个结构体的成员列表完全相同,如果它们被声明为不同的类型(即使是匿名的),那么它们仍然是不同的类型。
4、结构体变量的初始化
在C语言中,当您定义一个结构体时,可以为其成员变量提供初始值。这种操作称为结构体的初始化。初始化时,您可以使用大括号{}
来包含一系列初始化器,这些初始化器的顺序应当与结构体定义中的成员声明顺序一致。每个初始化器由逗号分隔。
(1)基本的结构体定义和初始化:
struct Person {int age;char name[20];int height;
};struct Person z = { 18, "zhangsan", 180 };
(2)匿名结构体的定义和初始化
为了声明一个匿名结构体的实例,需要先给结构体定义一个别名,或者直接在声明时提供一个变量名。如果想要声明一个匿名结构体并立即创建一个该类型的实例,可以用下列方法:
(i)直接在声明时初始化结构体变量:
struct {int age;char name[20];int height;
} z = { 18, 'zhangsan', 180 };
(ii)给匿名结构体定义一个别名:
typedef struct
{int age;char name[20];int height;
} Person;Person z = { 18, "zhangsan", 180 };
Person w = { 19, "wanger", 190 };
这里初始化变量时不能用:
struct Person z = { 18, "zhangsan", 180 };
这是错误的。
因为使用了typedef
,所以在定义变量时应该直接使用别名Person
,而不是struct Person
。正确的声明应该是:
Person z = { 18, "zhangsan", 180 };
如果使用struct Person
,编译器会认为你正在尝试声明一个新的、不同的结构体类型,它没有找到这个新类型的定义,因此会报告“不完整的类型”的错误。
这与有标签的结构体不同。
5、结构体的成员
(1)成员种类
在C语言中,结构体的成员可以是几乎任何类型,包括:
-
基本数据类型:如
int
,float
,double
,char
等。 -
数组类型:可以是基本数据类型的数组,例如
int numbers[10];
,也可以是结构体类型的数组。 -
指针类型:包括指向基本数据类型、数组、其他结构体或者函数的指针。
-
结构体类型:
- 同类型的结构体指针(因为直接包含同类型的结构体会造成无限大小的定义)。
- 其他类型的结构体或结构体数组,常用于嵌套结构体。
-
联合体(union)类型:可以包含联合体,它是一种特殊的数据结构,允许在相同的内存位置存储不同的数据类型。
-
枚举类型(enum):可以包含枚举类型成员,用于表示成员变量只能取有限个命名的整数值。
-
函数指针类型:可以包含指向函数的指针,这允许结构体“拥有”可以调用的函数。
下面是一个包含不同类型成员的结构体示例:
#include <stdio.h>// 声明一个枚举类型
enum Color
{ RED, GREEN, BLUE
};// 定义一个结构体类型
struct Example
{int integer; // 基本数据类型double floating_point; // 基本数据类型char character; // 基本数据类型char string[100]; // 数组类型int *pointer; // 指针类型struct Nested{float nested_floating_point;} nested_struct; // 嵌套结构体类型union{int union_int;float union_float;} union_member; // 联合体类型enum Color color; // 枚举类型void (*function_pointer)(void); // 函数指针类型
};// 一个简单的函数,之后会被赋给结构体中的函数指针
void simpleFunction()
{printf("Hello from simpleFunction!\n");
}int main()
{struct Example example;example.integer = 10;example.floating_point = 3.14;example.character = 'A';example.string[0] = '\0'; // 初始化字符串为空字符串int value = 20;example.pointer = &value; // 指向value的指针example.nested_struct.nested_floating_point = 2.71;example.union_member.union_float = 5.55f; // 使用联合体的float成员example.color = RED; // 枚举类型成员赋值example.function_pointer = simpleFunction; // 函数指针赋值// 使用函数指针调用函数example.function_pointer();return 0;
}
(2)结构体内包含其他结构体或包含指向自己结构体类型的指针
结构体的成员可以包含其他结构体,也可以包含指向自己结构体类型的指针,而通常这种指针的应用是为了实现一些更高级的数据结构如链表和树等。
以下是一个使用自引用指针的结构体定义,这个结构体可以用来实现一个简单的单向链表节点:
#include <stdio.h>struct ListNode
{int value; // 这个节点存储的数据struct ListNode* next; // 指向下一个节点的指针
};int main()
{// 创建链表节点struct ListNode node1;node1.value = 1;node1.next = NULL; // 目前链表只有一个节点,所以next指向NULL// 添加第二个节点struct ListNode node2;node2.value = 2;node2.next = NULL;// 将第一个节点的next指针指向第二个节点node1.next = &node2;// 现在,node1.next指向node2,形成了一个包含两个节点的链表return 0;
}
如果两个结构体互相包含,则需要对其中一个结构体进行不完整声明,如下所示:
struct B;//对结构体B进行不完整声明 struct A//结构体A中包含指向结构体B的指针{struct B* partner;//other members;};//结构体B中包含指向结构体A的指针,在A声明完后,B也随之进行声明struct B{struct A* partner;//other members;};
二、结构体的使用
1、. 点操作符(成员访问操作符)
格式:
结构体变量.成员
实例:
#include <stdio.h>struct Student
{char name[20];double height;int age;
};int main()
{struct Student a = {"xiaoa",1.80,19};printf("%s %lf %d",a.name,a.height,a.age);return 0;
}
运行结果:
也可以使用指针,但 . 操作符的优先级大于 * 操作符,要加()
#include <stdio.h>struct Student
{char name[20];double height;int age;
};int main()
{struct Student a = {"xiaoa",1.80,19};struct Student* pa = &a;printf("%s %lf %d",(*pa).name,(*pa).height,(*pa).age);return 0;
}
运行结果:
2、->箭头操作符(成员访问操作符)
格式:
结构体变量的指针->成员
实例:
#include <stdio.h>struct Student
{char name[20];double height;int age;
};int main()
{struct Student a = {"xiaoa",1.80,19};struct Student* pa = &a;printf("%s %lf %d\n",pa->name,pa->height,pa->age);return 0;
}
运行结果:
三、结构体做函数参数
1、直接传结构体变量
这种方法占用内存和时间较多,因为要将实参拷贝成形参需要时间,形参存储需要内存空间。
#include <stdio.h>struct Student//定义结构体
{char name[20];double height;int age;
};void print(struct Student student)//定义函数
{printf("名字 %s\n",student.name);printf("身高 %lf\n", student.height);printf("年龄 %d\n", student.age);
}int main()
{struct Student a = {"xiaoa",1.80,19};//定义和初始化结构变量astruct Student b = {"xiaob",1.85,18};//定义和初始化结构变量bprint(a);//利用print函数输出结构变量aprint(b);//利用print函数输出结构变量breturn 0;
}
运行结果:
2、传结构体变量的指针
这种方法更节省空间,不用创建形参。
#include <stdio.h>struct Student//定义结构体
{char name[20];double height;int age;
};void print(struct Student *student)
{printf("名字 %s\n", student->name);printf("身高 %lf\n", student->height);printf("年龄 %d\n", student->age);
}int main()
{struct Student a = { "xiaoa",1.80,19 };//定义和初始化结构变量astruct Student b = { "xiaob",1.85,18 };//定义和初始化结构变量bprint(&a);//传入结构体变量a的地址print(&b);//传入结构体变量b的地址return 0;
}
运行结果:
相关文章:

C语言——结构体
一、结构体的创建 1、定义 在 C 语言中,结构体是一种自定义的数据类型,它允许将不同类型的数据项组合成一个单一实体。这在组织复杂数据时非常有用,因为它可以将有逻辑关系的数据组合在一起。结构体是一些值的集合,这些值是结构…...

基于多反应堆的高并发服务器【C/C++/Reactor】(中)Buffer的创建和销毁、扩容、写入数据
TcpConnection:封装的就是建立连接之后得到的用于通信的文件描述符,然后基于这个文件描述符,在发送数据的时候,需要把数据先写入到一块内存里边,然后再把这块内存里边的数据发送给客户端,除了发送数据,剩下…...

【Linux】常用的基本命令指令①
前言:从今天开始,我们逐步的学习Linux中的内容,和一些网络的基本概念,各位一起努力呐! 💖 博主CSDN主页:卫卫卫的个人主页 💞 👉 专栏分类:数据结构 👈 💯代码…...
活动运营常用的ChatGPT通用提示词模板
活动目标确定:如何明确活动的目标,确保活动策划与执行的方向性? 活动主题选择:如何选择吸引人的活动主题,提高用户的参与度和兴趣? 活动形式策划:如何根据活动目标和主题,选择适合…...
SpringBoot 中实现订单30分钟自动取消的策略
简介 在电商和其他涉及到在线支付的应用中,通常需要实现一个功能:如果用户在生成订单后的一定时间内未完成支付,系统将自动取消该订单。 本文将详细介绍基于Spring Boot框架实现订单30分钟内未支付自动取消的几种方案,并提供实例…...

像专家一样使用TypeScript映射类型
掌握TypeScript的映射类型,了解TypeScript内置的实用类型是如何工作的。 您是否使用过Partial、Required、Readonly和Pick实用程序类型? 你知道他们内部是怎么运作的吗? 如果您想彻底掌握它们并创建自己的实用程序类型,那么不要错过本文所涵盖的内容。…...
Golang 结构体
前言 在 Go 语言中,结构体(struct)是一种自定义的数据类型,将多个不同类型的字段(fields)组合在一起 结构体通常用于模拟真实世界对象的属性和行为 定义结构体 可以使用 type 关键字和 struct 关键字来定…...

服务器运行状况监控工具
服务器运行状况监视提供了每个服务器状态和性能的广泛概述,通过监控服务器指标,如 CPU 使用率、内存消耗、I/O、磁盘使用率、进程等,服务器运行状况监控可以避免服务器停机。 服务器性能监控指标 服务器是网络中最重要的组件之一࿰…...
2022年全国职业院校技能大赛软件测试赛题卷②—自动化测试解析报告(含术语)
2022年全国职业院校技能大赛软件测试任务四 自动化测试 目录 第一题:按照以下步骤在PyCharm中进行自动化测试脚本编写,并执行脚本。...

497 蓝桥杯 成绩分析 简单
497 蓝桥杯 成绩分析 简单 //C风格解法1,*max_element()与*min_element()求最值 //时间复杂度O(n),通过率100% #include <bits/stdc.h> using namespace std;using ll long long; const int N 1e4 …...

一、HTML5简介
一、简介 超文本标记语言(英语:HyperText Markup Language,简称:HTML)是一种用于创建网页的标准标记语言。可以使用 HTML 来建立自己的 WEB 站点,HTML 运行在浏览器上,由浏览器来解析。 <!…...

视频云存储/视频智能分析平台EasyCVR在麒麟系统中无法启动该如何解决?
安防视频监控/视频集中存储/云存储/磁盘阵列EasyCVR平台可拓展性强、视频能力灵活、部署轻快,可支持的主流标准协议有国标GB28181、RTSP/Onvif、RTMP等,以及支持厂家私有协议与SDK接入,包括海康Ehome、海大宇等设备的SDK等。平台既具备传统安…...

前端性能优化之图像优化
图像优化问题主要可以分为两方面:图像的选取和使用,图像的加载和显示。 图像基础 HTTP Archive上的数据显示,网站传输的数据中,60%的资源都是由各种图像文件组成的,当然这些是将各类型网站平均的结果,单独…...

微信小程序封装vant 下拉框select 单选组件
先上效果图: 主要是用vant 小程序组件封装的:vant 小程序ui网址:vant-weapp 主要代码如下: 先封装子组件: select-popup 放在 components 文件夹里面 select-popup.wxml: <!--pages/select-popup/select-popup.wxml--> &…...
c语言试卷
江西财经大学IT帮 2020-2021第一学期期末C语言模拟考试试卷 课程名称:C语言程序设计(软件)(主干课程) 适用对象:21级本科 试卷命题人 钟芳盛 游天悦 李俊贤 万军豪 张位 试卷审核人 钟芳盛 一、单项…...

文献阅读:Sparse Low-rank Adaptation of Pre-trained Language Models
文献阅读:Sparse Low-rank Adaptation of Pre-trained Language Models 1. 文章简介2. 具体方法介绍 1. SoRA具体结构2. 阈值选取考察 3. 实验 & 结论 1. 基础实验 1. 实验设置2. 结果分析 2. 细节讨论 1. 稀疏度分析2. rank分析3. 参数位置分析4. 效率考察 4.…...

NCC基础开发技能培训
YonBuilder for NCC 是一个带插件的eclipse工具,跟eclipse没什么区别 NC Cloud2021.11版本开发环境搭建改动 https://nccdev.yonyou.com/article/detail/495 不管是NC Cloud 新手还是老NC开发,在开发NC Cloud时开发环境搭建必看!ÿ…...

Flink中的状态管理
一.Flink中的状态 1.1 概述 在Flink中,算子任务可以分为有状态和无状态两种状态。 无状态的算子任务只需要观察每个独立事件,根据当前输入的数据直接转换输出结果。例如Map、Filter、FlatMap都是属于无状态算子。 而有状态的算子任务,就…...

【linux】线程互斥
线程互斥 1.线程互斥2.可重入VS线程安全3.常见锁的概念 喜欢的点赞,收藏,关注一下把! 1.线程互斥 到目前为止我们学了线程概念,线程控制接下来我们进行下一个话题,线程互斥。 有没有考虑过这样的一个问题,…...

机器学习原理到Python代码实现之LinearRegression
Linear Regression 线性回归模型 该文章作为机器学习的第一篇文章,主要介绍线性回归模型的原理和实现方法。 更多相关工作请参考:Github 算法介绍 线性回归模型是一种常见的机器学习模型,用于预测一个连续的目标变量(也称为响应变…...

循环冗余码校验CRC码 算法步骤+详细实例计算
通信过程:(白话解释) 我们将原始待发送的消息称为 M M M,依据发送接收消息双方约定的生成多项式 G ( x ) G(x) G(x)(意思就是 G ( x ) G(x) G(x) 是已知的)࿰…...
【磁盘】每天掌握一个Linux命令 - iostat
目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...
GitHub 趋势日报 (2025年06月08日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...
MySQL中【正则表达式】用法
MySQL 中正则表达式通过 REGEXP 或 RLIKE 操作符实现(两者等价),用于在 WHERE 子句中进行复杂的字符串模式匹配。以下是核心用法和示例: 一、基础语法 SELECT column_name FROM table_name WHERE column_name REGEXP pattern; …...

深度学习习题2
1.如果增加神经网络的宽度,精确度会增加到一个特定阈值后,便开始降低。造成这一现象的可能原因是什么? A、即使增加卷积核的数量,只有少部分的核会被用作预测 B、当卷积核数量增加时,神经网络的预测能力会降低 C、当卷…...

中医有效性探讨
文章目录 西医是如何发展到以生物化学为药理基础的现代医学?传统医学奠基期(远古 - 17 世纪)近代医学转型期(17 世纪 - 19 世纪末)现代医学成熟期(20世纪至今) 中医的源远流长和一脉相承远古至…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...

【大模型】RankRAG:基于大模型的上下文排序与检索增强生成的统一框架
文章目录 A 论文出处B 背景B.1 背景介绍B.2 问题提出B.3 创新点 C 模型结构C.1 指令微调阶段C.2 排名与生成的总和指令微调阶段C.3 RankRAG推理:检索-重排-生成 D 实验设计E 个人总结 A 论文出处 论文题目:RankRAG:Unifying Context Ranking…...
手动给中文分词和 直接用神经网络RNN做有什么区别
手动分词和基于神经网络(如 RNN)的自动分词在原理、实现方式和效果上有显著差异,以下是核心对比: 1. 实现原理对比 对比维度手动分词(规则 / 词典驱动)神经网络 RNN 分词(数据驱动)…...

若依项目部署--传统架构--未完待续
若依项目介绍 项目源码获取 #Git工具下载 dnf -y install git #若依项目获取 git clone https://gitee.com/y_project/RuoYi-Vue.git项目背景 随着企业信息化需求的增加,传统开发模式存在效率低,重复劳动多等问题。若依项目通过整合主流技术框架&…...