C语言结构体详解(一)(能看懂文字就能明白系列)

🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟个人主页:  古德猫宁-    🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟

目录

结构的声明

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

结构体变量的创建

结构体的初始化

结构的特殊声明

 访问结构成员

结构体的自引用


引子:假如我们要设计一个程序来打印一份图书目录,打印每本书的各种信息:书名、作者、出版社、版权日期、页数和价格等。其中的一些项目(书名,作者)可以存储在字符数组中,其他项目需要一个int数组或者float数组来存储(价格,页数)。这样用七个不同的数组分别记录每一项的内容比较麻烦,且需要开辟许多空间,特别是要创建多份列表的时候。

所以,我们需要一种既可以包含字符串又能包含数字的数据形式,而且还要保持各信息的独立,C语言中的结构体就能满足你的需求,接下来让我来介绍结构体是什么,有什么用,怎么用。

结构的声明

结构声明描述了一个结构的组织布局,声明如下:

struct tag
{
   member- list ;
}variable- list ;

 假设要创建一个图书目录的结构:

struct book
{char title[20];//书名int value;//价格char author[20];//作者//…………
};

该声明描述了一个由俩个字符数组和一个int类型变量组成的结构。该声明并未创建实际的数据对象,只是描述了该对象由什么组成。(有时候我们把结构声明成为模板,因为它勾勒出结构是如何存储数据的)

接下来解释上面的一些细节,首先是关键字struct,它表明跟在其后的是一个结构,后面是一个可选的标记(上面是book),后面的程序中可以使用该标记引用该结构。所以,我们在后面的程序中可以这样声明:

struct book library

 这里libiary声明为一个使用book结构布局的结构变量。

在结构声明中,用一对花括号括起来的是成员列表。每个成员都用自己的声明来描述,成员可以是任意一种C语言的数据类型

最后括号后面的分号是必需的(不能省略),因为它表示结构布局定义结束。

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

1、结构体变量的创建

声明完结构之后,我们就要来创建结构体变量和初始化了

首先,结构有两层含义,一层含义是“结构布局”,结构布局告诉编译器如何表示数据,但是它并未让编译器为数据分配空间,所以接下来就是创建一个结构变量,即是结构的另一层含义。

程序中创建结构变量的一行是:

struct book library

 编译器执行这行代码便会创建一个结构变量library。编译器使用book模板为该变量分配空间:

一个内含20个元素的字符数组title,一个内含20个元素的字符数组author,一个int类型变量

这些存储空间都与一个名称library结合在一起。

例如下图:

在结构声明的变量中,struct book 所起的作用相当于一般声明中的int或float。

例如:可以定义两个struct book类型的变量,或者是指向struct book 类型结构的指针:

struct book 
{ //结构体成员char title[20];//书名int  value;//价格char author[20];//作者
};
struct book library1;//定义结构体变量1
struct book library2;//定义结构体变量2
struct book *pst;//定义指向结构体的指针
pst = &library;//将指针指向结构体变量

2、结构体的初始化

struct book
{char title[20];//书名int value;//价格char author[20];//作者//…………
};
int main()
{//按照结构体成员的顺序来初始化struct book library = { "C Primer Plus",99,"史蒂夫-普拉达" };//未按照结构体成员的顺序来初始化
struct book library = { .author = "史蒂夫 - 普拉达",.title = "C Primer Plus" ,.value = 99 };return 0;
}

 当然,我们也可以通过将指针指向结构体变量的地址,使用指针来访问和修改结构体的成员;

#include<stdio.h>
struct book 
{ //结构体成员char title[20];//书名int  value;//价格char author[20];//作者
};
int main()
{struct book library;//定义结构体变量struct book* pst = &library;//定义指向结构体的指针,将指针指向结构体变量pst->value = 30;//通过指针修改结构体成员return 0;
}

结构的特殊声明

在声明结构的时候,可以不完全声明

struct
{int a;char b;float c;
}x;struct
{int a;char b;float c;
}s[20], *p;//这里表示创建了一个包含20个元素的结构体数组s,每个元素包含一个整数a,一个字符b,一个浮点数c
//同时定义了一个指向这个结构体类型的指针p

上面的结构体在声明的时候省略掉了结构体标签(tag),称为匿名结构体

注意:

匿名的结构体类型,如果没有对结构体类型重命名的话,基本上只能使用一次。

编译器会把上面的两个声明当成完全不同的两个类型。

//所以在上面的两个结构体代码基础上,下面的代码是非法的

p=&x;

访问结构成员

结构类似于一个“超级数组”,这个超级数组中,可以是一个元素为char类型,下一个元素为float类型,下一个元素为int数组。我们可以通过数组下标单独访问数组中的各元素,那么,如何访问结构中的成员?

使用结构成员运算符——点(.)访问结构中的成员。

例如:

struct book
{char title[20];//书名int value;//价格char author[20];//作者//…………
};
int main()
{//按照结构体成员的顺序来初始化struct book library = { "C Primer Plus",99,"史蒂夫-普拉达" };//未按照结构体成员的顺序来初始化struct book library = { .author = "史蒂夫 - 普拉达",.title = "C Primer Plus" ,.value = 99 };printf("title:%s\n", library.title);printf("value:%d\n", library.value);printf("author:%s\n", library.author);return 0;
}

结构体的自引用

在结构体中包含一个类型为该结构本身的成员是否可以呢?

比如,定义一个链表的节点;

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

上述的代码是否正确,如果正确的话,那sizeof(struct Node)是多少

仔细分析,其实是不行的,因为一个结构体中再包含一个同类型的结构体变量,这样结构体变量的大小就会无穷的大,是不合理的。

正确的自引用方式:
 

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

在结构体自引用使用的过程中,夹杂了typedef对匿名结构体类型重命名,也容易引入问题,看看下面的代码有无错误:
 

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

答案是不行的,因为Node是对前面的匿名结构体类型的重命名产生的,但是在匿名结构体内部提前使用Node类型来创建成员变量,这是不行的。

解决方案如下:定义结构体不要使用匿名结构体了

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

本章是对于C语言结构体的简介,下篇将持续介绍有关结构体的内容

感谢各位观看

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

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

相关文章

简单聊聊更快、更稳、更高效的 QUIC 协议

目录 QUIC的起源和发展 QUIC 与 TCP 和 UDP 的比较 QUIC 的主要特性 QUIC 的工作原理 QUIC 的应用场景 小结 QUIC&#xff08;Quick UDP Internet Connections&#xff0c;快速 UDP 互联网连接&#xff09;是一种基于 UDP 协议的传输层协议&#xff0c;由 Google 首次提出…

上个班而已

习惯性刷CSDN&#xff0c;发现了这么个主题&#xff0c;有意思。在我的字典里&#xff0c;“养生”这个条目已经被我删了。看过了太多的伪科学、贩卖焦虑、带货、自以为是&#xff0c;干脆眼不见为净。但程序员人均亚健康这句话真未必是个玩笑&#xff0c;所以还是凑个热闹聊上…

XML Schema中的elementFormDefault

XML Schema中的elementFormDefault&#xff0c;用以指明xml的元素是否必须有命名空间的前缀。 它的取值可以为qualified、或者unqualified。默认值为unqualified。 当取值为qualified时&#xff0c;xml元素前必须有命名空间作为前缀&#xff1b; 当取值为unqualified时&#x…

04.PostgreSQL是如何实现隔离级别的?

PostgreSQL是如何实现隔离级别的&#xff1f; 事务有哪些特性&#xff1f; 事务看起来感觉简单&#xff0c;但是要实现事务必须要遵守 4 个特性&#xff0c;分别如下&#xff1a; 原子性&#xff08;Atomicity&#xff09;&#xff1a;一个事务中的所有操作&#xff0c;要么…

Istio新架构揭秘:环境化Mesh

自问世以来&#xff0c;Istio因其使用Sidecar&#xff08;可编程代理与应用容器一同部署&#xff09;而备受认可。这种架构选择使Istio用户能够享受其好处&#xff0c;而无需对其应用进行 drast 改变。这些可编程代理&#xff0c;与应用容器紧密部署在一起&#xff0c;因其能够…

CC++枚举类型与类型定义(typedef)

在C中&#xff0c;枚举类型&#xff08;enum&#xff09;和类型定义&#xff08;typedef&#xff09;都是用来为数据类型创建别名的机制。它们可以提高代码的可读性和维护性。 枚举类型&#xff08;enum&#xff09; 枚举类型是一种用户自定义的数据类型&#xff0c;用于定义…

java学习part27线程死锁

基本就是操作系统的内容 138-多线程-线程安全的懒汉式_死锁_ReentrantLock的使用_哔哩哔哩_bilibili

【大模型】更强的 ChatGLM3-6B 来了,开源可商用

【大模型】更强的 ChatGLM3-6B 来了&#xff0c;开源可商用 简介ChatGLM3-6B 环境配置环境搭建安装依赖 代码及模型权重拉取拉取 ChatGLM3-6B拉取 ChatGLM3-6B 模型权重及代码 终端测试网页测试安装 gradio加载模型并启动服务 参考 简介 ChatGLM3-6B ChatGLM3-6B 是 ChatGLM …

总结 SpringMVC 中的常用注解和用法

RequestMapping ??是?Spring?Web?MVC?应⽤程序中最常被⽤到的注解之⼀&#xff0c;它是⽤来注册接⼝的 路由映射的.? 表⽰服务收到请求时,?路径为?/sayHi?的请求就会调⽤?sayHi?这个⽅法的代码.?? 路由映射:?当⽤⼾访问⼀个?URL?时,?将⽤⼾的请求对应到程序中…

thinkphp控制器调用脚本

一、同步方式 //脚本配置示例protected function configure(){// 指令配置$this->setName(pltUpgrade)->addArgument(type, Argument::OPTIONAL, your type)->addOption(id, null, Option::VALUE_REQUIRED, upgrade id)->setDescription(PltUpgrade);}// 调用命令行…

基于STM32的四轴飞行器的控制系统(论文+源码)

1.系统设计 本次基于stm32单片机的四轴飞行器控制系统主要包括硬件和软件这两大部分&#xff0c;其中硬件部分是基于单片机的四轴飞行器控制系统实现的基石&#xff0c;其中主要STM32单片机负责整个系统功能的实现&#xff1b;NRF24L01无线模块负责对四轴飞行器的远程控制&…

rtmp 协议详解

1. handshake 1.1 概述 rtmp 连接从握手开始。它包含三个固定大小的块。客户端发送的三个块命名为 C0,C1,C2&#xff1b;服务端发送的三个块命名为 S0,S1,S2。 握手序列&#xff1a; 客户端通过发送 C0 和 C1 消息来启动握手过程。客户端必须接收到 S1 消息&#xff0c;然后…

MS721仪表总线收发器可Pin to Pin兼容TSS721A

MS721 是为 M-Bus 标准&#xff08;EN1434-3&#xff09;的应用而开发的单片收发电路。MS721 接口电路可以适应从站与主站之间的电压差&#xff0c;总线的连接没有极性要求&#xff0c;电路由主站通过总线供电&#xff0c;这样对于从站电池就不会增加额外的负载&#xff0c;同时…

轻量级万物分割SAM模型——MobileSAM安装实测摘要

目录 0、前言1、准备工作安装python环境说明安装说明 运行测试app安装依赖修改代码 2、实际测试效果自带图片测试其它图片测试1其它图片测试2 总结 0、前言 本文将介绍一种轻量级万物分割SAM模型——MobileSAM的安装和实测情况。SAM是meta公司的一种图像分割大模型&#xff0c…

二分+dp:[ARC120E] 1D Party

https://www.luogu.com.cn/problem/AT_arc120_e 考虑二分时间&#xff0c;然后设 d p ( i , 0 ) dp(i,0) dp(i,0) 表示第 i i i 个人开头往左走&#xff0c;掉头后剩余步数。 d p ( i , 1 ) dp(i,1) dp(i,1) 表示第 i i i 个人先往右走&#xff0c;最多走多少步就有掉头。 …

css中的 Grid 布局

flex布局和grid布局区别 flex布局是 一维布局grid布局是二维布局 flex布局示例 grid布局示例 grid 布局初体验 体验地址 <div class"wrapper"><div class"one item">One</div><div class"two item">Two</div&…

Asp.net core WebApi 配置自定义swaggerUI和中文注释,Jwt Bearer配置

1.创建asp.net core webApi项目 默认会引入swagger的Nuget包 <PackageReference Include"Swashbuckle.AspNetCore" Version"6.2.3" />2.配置基本信息和中文注释&#xff08;默认是没有中文注释的&#xff09; 2.1创建一个新的controller using Micr…

开源堡垒机Jumpserver

文章目录 开源堡垒机JumpserverJumpserver介绍安装环境部署安装jumpserver访问jumpserver的web界面 开源堡垒机Jumpserver Jumpserver介绍 Jumpserver 是全球首款完全开源的堡垒机&#xff0c;使用 GNU GPL v2.0 开源协议&#xff0c;是符合 4A 的运维安全审计系统。 Jumpse…

一、个人博客搭建保姆级教程-总篇

前言 首先说明一下&#xff0c;我们这套教程主要部署的是静态网页&#xff0c;即不涉及到JavaWeb、ASP.Net这些框架。直接使用nginx托管静态网页。 主要面向的是不希望花太多时间在搭建个人博客上的小伙伴、以及非程序员的小伙伴。 前置知识 当然了&#xff0c;搭建需要一些…

项目代码规范

Web端代码规范 Vue项目代码规范 一、命名规范 1、项目名 全部采用小驼峰命名式&#xff0c;例&#xff1a;camelCase&#xff08;小驼峰式命名法 —— 首字母小写&#xff09; 2、目录名 参照项目命名规则&#xff0c;有复数结构时&#xff0c;要采用复数命名法。例&#xff…