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

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

                                                             专栏:​​​​​​深入理解计算机系统​​​​​

                                                                        C语言基础习题 

                                                                        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语言结构体的简介,下篇将持续介绍有关结构体的内容

感谢各位观看

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

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

相关文章

Gateway跨域解决可copy配置代码

globalcors: # 全局跨域处理配置add-to-simple-url-handler-mapping: true # 解决options请求被拦截的问题cors-configurations:[/**]:allowed-origins:- "http://localhost:8090"- "http://www.qvfan.com"allowedMethods:- "GET"- "POST&q…

C++相关闲碎记录(3)

1、reference wrapper 例如声明如下的模板&#xff1a; template <typename T> void foo(T val); 如果调用使用&#xff1a; int x; foo(std::ref(x)); T变成int&&#xff0c;而使用调用 int x; foo(std::cref(x)); T变成const int&。 这个特性被C标准库用…

【每日一题】1094. 拼车-2023.12.2

题目&#xff1a; 1094. 拼车 车上最初有 capacity 个空座位。车 只能 向一个方向行驶&#xff08;也就是说&#xff0c;不允许掉头或改变方向&#xff09; 给定整数 capacity 和一个数组 trips , trip[i] [numPassengersi, fromi, toi] 表示第 i 次旅行有 numPassengersi…

vue中中的动画组件使用及如何在vue中使用animate.css

“< Transition >” 是一个内置组件&#xff0c;这意味着它在任意别的组件中都可以被使用&#xff0c;无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发&#xff1a; 由 v-if 所触发的切换由 v-show 所触…

@2023 中国家居家具行业数字化转型分析与案例解读|商派徐礼昭

作者&#xff1a;徐礼昭&#xff08;商派市场负责人&#xff0c;重构零售实验室负责人&#xff09; 中国的家居家具行业面临着市场竞争激烈、消费者需求多变等诸多挑战。为了应对这些挑战&#xff0c;许多品牌企业开始探索数字化转型的道路&#xff0c;以提升竞争力并满足消费…

非应届生简历模板13篇

无论您是职场新人还是转行求职者&#xff0c;一份出色的简历都是获得心仪岗位的关键。本文为大家精选了13篇专业的非应届生简历模板&#xff0c;无论您的经验如何&#xff0c;都可以灵活参考借鉴&#xff0c;提升自己的简历质量。让简历脱颖而出&#xff0c;轻松斩获心仪职位&a…

np.array无法直接用matplotlib画图,因为需要借用np.squeeze先转化

文章目录 前言一、使用步骤1.没使用np.squeeze转化2.使用np.squeeze转化 前言 实际工作中&#xff0c;时而难免会遇见np.array无法直接用matplotlib画图的情况&#xff0c;这个时候&#xff0c;是因为在画图之前少了一个步骤&#xff0c;需要先借用np.squeeze先转化 一、使用步…

ES通过抽样agg聚合性能提升3-5倍

一直以来&#xff0c;es的agg聚合分析性能都比较差&#xff08;对应sql的 group by&#xff09;。特别是在超多数据中做聚合&#xff0c;在搜索的条件命中特别多结果的情况下&#xff0c;聚合分析会非常非常的慢。 一个聚合条件&#xff1a;聚合分析请求的时间 search time a…

【算法】Rabin-Karp 算法

目录 1.概述2.代码实现3.应用 更多数据结构与算法的相关知识可以查看数据结构与算法这一专栏。 有关字符串模式匹配的其它算法&#xff1a; 【算法】Brute-Force 算法 【算法】KMP 算法 1.概述 &#xff08;1&#xff09;Rabin-Karp 算法是由 Richard M. Karp 和 Michael O. R…

免费采集工具推荐,好文章值得收藏

采集工具的作用 在互联网的海洋中&#xff0c;有许多强大的免费采集工具&#xff0c;它们为用户提供了便捷、高效的方式&#xff0c;帮助用户从各种网站中收集、整理所需的信息。这些工具不仅广泛应用于市场研究、竞争情报等商业领域&#xff0c;同时也服务于学术研究、个人兴…

虚函数表和虚函数在内存中的位置

文章目录 结论验证 结论 虚函数表指针是虚函数表所在位置的地址。虚函数表指针属于对象实例。因而通过new出来的对象的虚函数表指针位于堆&#xff0c;声名对象的虚函数表指针位于栈 虚函数表位于只读数据段&#xff08;.rodata&#xff09;&#xff0c;即&#xff1a;C内存模…

量子测量-技术点杂录

目录: 高质量文章导航-持续更新中_GZVIMMY的博客-CSDN博客 前置:量子测量设备 电子显微镜:电子显微镜可以在非常高分辨率下观察生物组织、细胞和分子结构。通过调整电子束的强度和聚焦来观察细胞内部的微小结构。但是,电子显微镜需要对样品进行切片处理,而且在真空中进行…

配置中心--Spring Cloud Config

目录 概述 环境说明 步骤 创建远端git仓库 准备配置文件 配置中心--服务端 配置中心--客户端 配置中心的高可用 配置中心--服务端 配置中心--客户端 消息总线刷新配置 配置中心--服务端 配置中心--客户端 概述 因为微服务架构有很多个服务&#xff0c;手动一个一…

Xilinx FPGA平台DDR3设计详解(二):DDR SDRAM组成与工作过程

本文主要介绍一下DDR SDRAM的基本组成以及工作过程&#xff0c;方便大家更好的理解和掌握DDR的控制与读写。 一、DDR SDRAM的基本组成 1、SDRAM的基本单元 SDRAM的基本单元是一个CMOS晶体管和一个电容组成的电路。 晶体管最上面的一端&#xff0c;称作栅极&#xff0c;通过…

css实现简单的抽奖动画效果和旋转效果,还有春联效果

使用css的animation和transform和transition可以实现简单的图片放大缩小&#xff0c;旋转&#xff0c;位移的效果&#xff0c;由此可以延伸的动画效果还是挺多的&#xff0c;比如图片慢慢放大&#xff0c;图片慢慢旋转并放大&#xff0c;图片慢慢变化位置等等&#xff0c; 抽奖…

mall电商项目(学习记录2)

运行mall-admin Java项目 需要安装Redis&#xff0c;需要安装mysql&#xff0c;同时需要运行其项目提供的mall.sql 运行mall-admin后端程序 安装完Redis、mysql、HeidiSQL&#xff08;用于执行mall.sql&#xff0c;界面化操作高效直观&#xff09;、IntelliJ IDEA 运行mall-…

《算法通关村——原来滑动窗口如此简单》

《算法通关村——原来滑动窗口如此简单》 基本思想 滑动窗口的思想非常简单&#xff0c;如下图所示&#xff0c;假如窗口的大小是3&#xff0c;当不断有新数据来时&#xff0c;我们会维护一个大小为3的一个区间&#xff0c;超过3的就将新的放入老的移走。 这个过程有点像火车…

如何开发互联网医院系统源码?互联网医院小程序开发全流程解析

互联网医院系统源码的开发以及互联网医院小程序的设计是关键环节&#xff0c;本文将为您详细解析开发全流程。 一、需求分析与规划 第一步&#xff0c;明确系统的功能模块。同时&#xff0c;规划系统的整体架构、技术栈&#xff0c;在这里需要想到系统的可扩展性和性能。 二…

千梦网创:熟悉抖音内容创作的切入方式

因为身边抖音网红的资源比较近&#xff0c;所以虽然一直没有露脸去做短视频运营&#xff0c;但是最近也是跟随朋友一起开始了短视频的学习之路。 在参观过一些“超级直播间”之后&#xff0c;我们敲定了未来的两个盈利方向&#xff0c;这两个方向可以将我们身边的资源极致利用…

xxl-job 分布式任务调度框架

文章目录 分布式任务调度XXL-Job 简介XXL-Job 环境搭建XXL-Job (源码说明)配置部署调度中心docker安装 Bean模式任务(方法形式)-入门案例任务详解任务详解-执行器任务详解-基础配置任务详解-调度配置任务详解-基础配置任务详解-阻塞处理策略任务详解-路由策略 路由策略路由策略…