【C语言】详解结构体(上)

文章目录

  • 前言
  • 1. 结构体类型的含义
  • 2.结构体的声明
    • 2.1 结构体声明的语法
    • 2.2 结构体变量的创建和初始化
  • 3.结构体的特殊声明
  • 4. 结构体的自引用
  • 5.小结

前言

C语言的数据类型分为内置数据类型和自定义的数据类型。所谓的内置的数据类型可以认为是C语言自带的数据类型(char、int、float、double、bool),而自定义的数据类型(数组、结构体、联合体和枚举)中的结构体类型就是本文所要分享给大家的。

1. 结构体类型的含义

我们在正式学习结构体之前,得先了解一下结构体到底是个什么东西?
有句古话说的好:知己知彼,方能百战不殆。
我们想要学好结构体,就必须得对它有一定的了解。为了让大家能够更好的学习结构体,这里就先引入我们之前学过的数组的一些知识。

我们都是知道,数组里面的元素都是相同类型的,并且它们在内存空间中是连续存放的。那这时我们就会有这么一个疑惑?C语言有没有一种数据类型能够存放一次性包括多种不同的数据类型。答案是有的,那就是我们本讲的主角——结构体

总而言之,当我们在编程时遇到了一个个体,这个个体包含着许多不同的属性,一个一个定义就显得过于繁琐且不方便,那么结构体就刚好适应这种场景的需求。

2.结构体的声明

在讲完结构体的含义之后,那我们该如何去定义一个结构体呢?

2.1 结构体声明的语法

struct tag
{
	member-list; 
}varible-list;
符号含义
tag标签,可以理解为结构体名字
member-list成员列表,之后我们就是在这个花括号内来写我们想要存储的变量
varible-list变量列表,这个就是我们利用结构体创建之后直接给结构体变量的名称

注意:结构体名称和结构体变量名称是两个不一样的东西,不要给混淆了

例如:我们描述一个学生

struct Student
{
	char name[20];//姓名
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}; //这里有个分号,一定不要忘记写了

2.2 结构体变量的创建和初始化

struct S
{
	char c;
	int i;
	double d;
};

struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
};

int main()
{
	//按照结构体的成员顺序进行赋值
	struct Stu s1 = { "张三",22,"男","123456789" };
	printf("name: %s\n",s1.name);
	printf("age: %d\n", s1.age);
	printf("sex: %s\n", s1.sex);
	printf("id: %s\n", s1.id);

	printf("\n");
	//按照知道指定的顺序赋值
	struct Stu s2 = { .age = 18,.name = "梨花",.id = "563217485",.sex = "女"};
	printf("name: %s\n", s2.name);
	printf("age: %d\n", s2.age);
	printf("sex: %s\n", s2.sex);
	printf("id: %s\n", s2.id);
	return 0;
}

结果演示
除了上述在main函数内创建结构体变量的方式之外,我们还可以在面函数外面创建结构体变量,如果是这样做的话,这个变量就相当于全局变量了。

//方法一
struct Stu
{
	char name[20];//名字
	int age;//年龄
	char sex[5];//性别
	char id[20];//学号
}s1,s2; //变量列表

//方法二
struct Stu s3;

int main()
{
	...
}

3.结构体的特殊声明

在声明结构体时,我们也可以做到不完全声明。具体一点来讲,就是不给结构体名字。
我们将这种结构体称为“匿名结构体
比如:

//匿名结构体类型
struct
{
	int i;
	char ch;
	double d;
}s;
struct
{
	int i;
	char ch;
	double d;
}* ps;

可以观察到,匿名结构体在声明时,的确出现了省略标签(tag)的现象。

不过需要注意的是,匿名结构体只能用一次。这里的“用一次”也就是说该匿名结构体在本声明之初就应该一次性在变量列表中创建好所有变量的名称,等到脱离了匿名结构体的声明后,就再也没有办法创建一个新的结构体变量了。

那么我现在有个问题:

ps = &s; //这样写可以吗?

乍一看,好像确实没有什么问题啊!ps这个结构体指针所指向的结构体与结构体变量s里面的成员变量是一摸一样的。可事实真的如此吗?

错误警告

警告信息为:“=”: 从“*”“*”的类型不兼容
也就是说ps所指向的结构体与变量s所代表的结构体不属于同一个结构体类型,尽管它们里面成员一模一样

为此,我们总结一下匿名结构体使用的注意事项:

  1. 匿名结构体只能使用一次
  2. 即使两个甚至是多个匿名结构体里面的成员列表的内容是一摸一样的,编译器也会把这些结构体视作不同类型的结构体变量

4. 结构体的自引用

在结构体包含一个类型为改结构体本身的成员是否可以呢?
答案是肯定的,不过有一定的语法规则。为什么会这样说呢?请看下面的代码:

//根据上面的意思,我们可以写出以下代码:
struct Node
{
	int data;
	struct Node next;
};

上面的代码合理吗?如果合理的话,请告诉我sizeof(struct Node)的值为多少?
显然,问到这里,你就会发现,这个结构体这样声明确实有点问题。这个结构体的声明给我们一种陷入了死循环的感觉,而这个结构体的大小就为无穷大。

正确子引用的方式:

struct Node
{
	int data;
	struct Node* next;
};

我们用一个指向该结构体的指针作为该成员变量,这样做不仅可以知道该结构体的大小,还可以利用该指针访问其内部的数据,一举两得。

例外,我们还需要注意一种极其容易出现错误的写法:
我们再利用typedef给结构体重命名时:

typedef struct Node
{
	int data;
	Node* next;
}Node;

上述写法可行吗?
错误示范
原因是:编译器是从上往下来执行代码的,当执行到 Node* next 这条语句时,编译器由于还未完全读到typedef的所有语句,因此就将Node视作未定义的标识符。

正确的写法是:

typedef struct Node
{
	int data;
	struct Node* next;
}Node;

5.小结

在本文中,我想告诉大家的是:结构体的用途、结构体的声明、结构体的变量的创建及初始化还有结构体的自引用。内容不是很多,希望读者们能好好消化理解。

最后,如果觉得本文写的还不错的话,希望可以给偶带上个赞👍,阿里嘎多❤️❤️❤️。
让我们在详解结构体(下)这个篇章再见!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/798430.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【网络安全】基于PHP study的DVWA靶场搭建教程

PHP study的安装本文略过 DVWA安装地址 https://github.com/digininja/DVWA?tabreadme-ov-file将zip文件安装至PHP study的www目录下: 解压,进入config目录中,将.dist后缀删除: 接着打开该php文件,将用户名、密码改为…

程序包不存在【java: 程序包org.springframework.boot不存在】

1、问题提示:java: 程序包org.springframework.boot不存在 注意:已经下载好了程序包,就是提示不存在 2、解决办法

Qt5离线安装包无法下载问题解决办法

Qt5离线安装包无法下载问题解决办法 文章目录 Qt5离线安装包无法下载问题解决办法1、前言2、Qt5安装包下载办法 更多精彩内容👉个人内容分类汇总 👈👉Qt开发经验 👈 1、前言 Qt安装包官方下载地址 Qt5离线安装包目前在国内已经被墙…

链表的回文结构(链表的中间节点+反转链表)

链表的回文结构 一.链表的中间节点思路1:暴力求解思路2:快慢指针 二.返回倒数第k个节点思路1:暴力求解思路2:快慢指针 三.反转链表思路1:头插法思路2:反转指针的指向 四.链表的回文结构思路1:利…

react + redux 状态管理操作

目录 1 概念2 Redux 安装3 创建子模块并导入4 中间件为 react 注入 store5 在组件中使用 store 数据6 修改 store 数据7 提交 action 传参8 异步状态操作9 redux 调试工具 1 概念 Redux 是一个全局状态管理的 JS 库 2 Redux 安装 在react中使用redux,官方要求安…

css设置弹性flex后,如果设置100vh高度不撑满的原因

问题 父元素设置height为100%,有两个子元素,第一个设置height:100vh,第二个设置flex:1,此时第一个高度无法撑满盒子 原因解决方式 当父元素设置display为flex,第一个div设置高度64px,剩一个div设置高度为flex:1,这时…

DROO论文笔记

推荐文章DROO源码及论文学习 读论文《Deep Reinforcement Learning for Online Computation Offloading in Wireless Powered Mobile-Edge Computing Networks》的笔记 论文地址:用于无线移动边缘计算网络在线计算卸载的深度强化学习 论文代码地址:DR…

AG32 的MCU与FPGA的主频可以达到568MHz吗

Customers: AG32/ AGRV2K 这个芯片主频和定时器最高速度是多少?用户期望 CPLD计时器功能0.1ns以下。 AGM RE: CPLD做不到 0.1ns的速率,这个需要10G以上的时钟。 那AGRV2K最高多少MHz呢? 一般200MHZ比较容易实现。 进一步说明&#xff1…

Vulnhub靶场DC-3-2练习

目录 0x00 准备0x01 主机信息收集0x02 站点信息收集0x03 漏洞查找与利用1. joomla漏洞查找2. SQL注入漏洞3. 破解hash4. 上传一句话木马5. 蚁剑连接shell6. 反弹shell7. 提权 0x04 总结 0x00 准备 下载链接:https://download.vulnhub.com/dc/DC-3-2.zip 介绍&#…

51单片机5(GPIO简介)

一、序言:不论学习什么单片机,最简单的外设莫过于I口的高低电平的操作,接下来,我们将给大家介绍一下如何在创建好的工程模板上面,通过控制51单片机的GPIO来使我们的开发板上的LED来点亮。 二、51单片机GPIO介绍&#…

数据结构初阶(C语言)-复杂度的介绍

在学习顺序表之前,我们需要先了解下什么是复杂度: 一,复杂度的概念 我们在进行代码的写作时,通常需要用到许多算法,而这些算法又有优劣之分,区分算法的优劣则是通过算法的时间复杂度和空间复杂度来决定。 …

python 怎样生成窗体

通过import tkinter导入Tkinter模块,没有这句下面的都不成立了。 wintkinter.Tk(),这句是创建windows的窗口对象,注意后面的Tk,大小写。 win.title("窗口"),这段是设置窗口上的标题。 另外窗口的大小你可以通…

Linux命令更新-Vim 编辑器

简介 Vim 是 Linux 系统中常用的文本编辑器,功能强大、可扩展性强,支持多种编辑模式和操作命令,被广泛应用于程序开发、系统管理等领域。 1. Vim 命令模式 Vim 启动后默认进入命令模式,此时键盘输入的命令将用于控制编辑器本身&…

云计算【第一阶段(31)】PXE高效批量网络装机

一、系统安装 1.1、系统装机的三种引导方式 1. 硬盘 2. 光驱( u 盘) 3. 网络启动 pxe 1.2、系统安装过程 加载boot loader Boot Loader 是在操作系统内核运行之前运行的一段小程序。通过这段小程序,我们可以初始化硬件设备、建立内存空间的映…

解决mysql,Navicat for MySQL,IntelliJ IDEA之间中文乱码

使用软件版本 jdk-8u171-windows-x64 ideaIU-2021.1.3 mysql-essential-5.0.87-win32 navicat8_mysql_cs 这个问题我调试了好久,网上的方法基本上都试过了,终于是解决了。 三个地方结果都不一样。 方法一 首先大家可以尝试下面这种方法&#xff1a…

无人驾驶大热,新能源汽车智能化中的算网支持

来源新华社:百度“萝卜快跑”全无人驾驶汽车行驶在路上 当前,新能源汽车产业数智化已成为全球汽车产业数字化转型的焦点。一方面,随着人工智能、大数据、云计算等技术的深度融合,新能源汽车在自动驾驶、智能互联、能源管理等方面…

【自动驾驶汽车通讯协议】UART通信详解:理解串行数据传输的基石

文章目录 0. 前言1. 同步通讯与异步通讯1.1 同步通信1.2 异步通信 2. UART的数据格式3. 工作原理3.1 波特率和比特率3.2 UART的关键特性 4. UART在自动驾驶汽车中的典型应用4.1 UART特性4.2应用示例 5. 结语 0. 前言 按照国际惯例,首先声明:本文只是我自…

STM32MP135裸机编程:BOOT跳转到APP前关闭所有中断、清除所有中断挂起标志操作方法

0 前言 一般来说,MCU/SOC的BOOT在跳转到APP前都需要进行环境清理的操作,其中必须进行的一项操作便是关闭所有中断、清除所有中断挂起标志。本文介绍基于STM32MP135裸机编程下关闭所有中断、清除所有中断挂起标志的操作方法。 1 操作方法 STM32MP135裸…

关于Kafka Topic分区和Replication分配的策略

文章目录 1. Topic多分区2. 理想的策略3. 实际的策略4. 如何自定义策略 1. Topic多分区 如图,是一个多分区Topic在Kafka集群中可能得分配情况。 P0-RL代表分区0,Leader副本。 这个Topic是3分区2副本的配置。分区尽量均匀分在不同的Broker上&#xff0c…

怎么减少pdf的MB,怎么减少pdf的大小

在数字化时代,pdf文件因其格式稳定、跨平台兼容性强等特点而广受欢迎。然而,随着内容的丰富,pdf文件的大小也日益增大,给文件传输和存储带来了不少困扰。本文将为你介绍多种减小pdf文件大小的方法,帮助你轻松应对这一问…