【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.小结

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Java案例遍历集合中的自定义对象

目录 一:案例要求: 二案例分析: ​编辑三:具体代码: 四:运行结果: 一:案例要求: 二案例分析: 三:具体代码: Ⅰ: pack…

Windows系统中MySQL的安装和卸载(详细包含msi和zip下载方式,以及完全卸载方法,易出现问题及解决方案等)

MySQL的安装: 第一种:msi安装(交简单,但是不能自定义安装路径) 下载地址:https://dev.mysql.com/downloads/installer/ 选择历史版本 选择安装版本,这里我选择的是8.0.37的版本,然…

【HarmonyOS】HarmonyOS NEXT学习日记:二、ArkTs语法

【HarmonyOS】HarmonyOS NEXT学习日记:二、ArkTs语法 众所周知TS是JS的超集,而ArkTs则可以理解为是Ts的超集。他们的基础都基于JS,所以学习之前最好就JS基础。我的学习重点也是放在ArkTs和JS的不同点上。 文章主要跟着官方文档学习,跳过了一…

框架设计MVC

重点: 1.用户通过界面操作,传输到control,control可以直接去处理View,或者通过模型处理业务逻辑,然后将数据传输给view。 2.control包含了model和view成员。 链接: MVC框架详解_mvc架构-CSDN博客 MVC架…

Spring Boot 学习总结(34)—— spring-boot-starter-xxx 和 xxx-spring-boot-starter 区别?

一、Spring Starter 简介 Spring Starter 是 Spring Boot 提供的一种便捷方式,帮助开发者快速集成和配置 Spring 应用中所需的依赖。每个 Starter 都是一个预配置的依赖集,可以自动配置应用的一部分或特定功能。这些 Starter 旨在消除手动编写大量样板代码和配置的需求。 1…

小程序中用于跳转页面的5个api是什么和区别

在微信小程序中,用于页面跳转的API主要有以下几个,但通常不需要5个那么多,因为它们的功能各有侧重,用于不同的跳转场景。以下是这些API及其详细代码和区别: wx.navigateTo(OBJECT) 用于保留当前页面,跳转到…

cn.hutool.core.util.IdUtil.getSnowflake

Hutool 是一个非常实用的 Java 工具库,其中包含了许多便捷的工具类和方法。IdUtil 是 Hutool 提供的一个用于生成唯一 ID 的工具类,而 getSnowflake 方法则是用于生成基于 Twitter 的 Snowflake 算法的分布式唯一 ID。 Snowflake 算法简介 Snowflake 算…

【Docker】Docker 的数据管理与镜像创建

目录 一.数据管理 1.数据卷 2.数据卷容器 二.端口映射 三.容器互联 四.Docker 镜像的创建 1.基于现有镜像创建 1.1.首先启动一个镜像,基于镜像创建容器,更新容器内容 1.2.将修改后的容器提交为新的镜像,需要使用该容器的 ID 号创建新…

算法2--贪心算法

1.老鼠和猫的交易 小老鼠准备了M磅的猫粮,准备去和看守仓库的猫做交易,因为仓库里有小老鼠喜欢吃的五香豆。 仓库有N个房间; 第i个房间有 J[i] 磅的五香豆,并且需要用 F[i] 磅的猫粮去交换; 老鼠不必交换该房间所有的五…

中国星坤X0800HI系列线对板连接器:创新技术连接,引领智能家居未来!

近日,中国星坤推出的X0800HI系列线对板连接器,凭借其独特的设计和卓越的性能,引起了业界的广泛关注。 X0800HI系列线对板连接器在极小空间内实现了线对板的W-B连接,这不仅解决了传统连接方式中剥线和焊接的繁琐步骤,还…

Netty UDP

Netty在UDP(用户数据报协议,User Datagram Protocol)通信中的应用非常广泛,特别是在对实时性要求较高、对数据准确性要求相对较低的场景中,如视频传输、语音通信等。以下是对Netty在UDP通信中的详细解析: …

django踩坑(四):终端输入脚本可正常执行,而加入crontab中无任何输出

使用crontab执行python脚本时,有时会遇到脚本无法执行的问题。这是因为crontab在执行任务时使用的环境变量与我们在终端中使用的环境变量不同。具体来说,crontab使用的环境变量是非交互式(non-interactive)环境变量,而终端则使用交互式(inter…

RANSAC-随机采样一致

一、RANSAC算法 RANSAC(Random Sample Consensus,随机抽样一致性算法)是一种迭代方法,用于从一组包含大量“外点”(不符合模型的数据点)的数据中估计数学模型的参数。它特别适用于同时包含“内点”&#x…

Hyper-V和VMWare使用对比

图片来自互联网 1.起因 最近在学习Linux相关的知识,第一步当然就是装虚拟机了。之前是基于微软Hyper-V平台装的Ubuntu,用起来总是感觉卡卡的。我还一直天真的以为虚拟机都是这个样子的,直到用了VMWare之后…。VMWare我主要装的是VMWare16Pro&#xff0…

224 |《乡下人的悲歌》也是城市中产的呜咽

今天《乡下人的悲歌》和他的作者火了:詹姆斯戴维万斯(James David Vance)被共和党提名为副总统候选人。 以下是最能代表这本书的一个重要观点: I dont believe in epiphanies. I dont believe in transformativemoments, as trans…

C++:链表插入排序/删除重复节点题解

插入排序 插入排序的思路很简单,基本都知道。 关键是放在链表中, 1.要建立一个哨兵位,这个哨兵位的下一个节点,始终指向val最小的节点。 2.prev指针作为cur的前一个节点,始终指向val最大的节点。它的下一个节点始终…

JavaFX+MySQL实现图书管理系统(包含完整代码)

目录 一、功能介绍 1.ER图 2.学生管理员登陆页面 3.图书馆首页 4.学生图书馆搜索界面 5.学生注册 6.管理员后台 增加书籍 查看借阅记录 ​编辑 修改图书 二、功能分解 1.界面展示 2.点击按钮切换页面 普通按钮点击 复杂按钮点击 3.登录注册 创建登陆注册的页…

逆向学习思路链接分享

学好逆向先学C 然后我们需要学习好 编码问题CTF常见编码及加解密(超全) - ruoli-s - 博客园 (cnblogs.com) 并且规划好学习路线 CTF逆向Reverse入门学习路线(面向小白)_逆向reverse 思路-CSDN博客 并且安好反编译的环境 x64d…

linux学习笔记整理: 关于linux系统介绍 2024/7/16;

介绍: Linux,全称GNU/Linux,是一种免费使用和自由传播的类UNIX操作系统,其内核由林纳斯本纳第克特托瓦兹(Linus Benedict Torvalds)于1991年10月5日首次发布,它主要受到Minix和Unix思想的启发,是…

java使用字符缓冲流读写文件莫名消失

张三 李四 王二 麻子 狗蛋 小明 这是文件里的内容 package com.lu.day11;import java.io.*; import java.util.Map; import java.util.Random; import java.util.stream.Collectors;public class Test3 {public static void main(String[] args) {try (BufferedReader buffered…