【C语言初阶(18)】结构体

文章目录

  • 前言
  • Ⅰ结构体的声明
  • Ⅱ 结构体的定义
  • Ⅲ 结构体初始化
  • Ⅳ 访问结构体成员
    • ⒈结构体变量访问结构体成员
    • ⒉结构体指针访问结构体成员
  • Ⅴ 结构体的嵌套
  • Ⅵ 结构体传参

前言

  • C 语言提供了一些非常基本的数据类型,如 int、float、double、char 等,这些不同的类型决定了一个变量在内存中应该占据的空间以及表现形式。

  • 但有时候面对的问题可能比较复杂,并不是这些基本的数据类型就可以解决的。

    • 例如,我想为 “ 好书推荐 ” 栏目写一个程序,用于采集每一本图书的信息,那么就需要用到一个变量来统一存放一本书涉及的多个数据。

    在这里插入图片描述

  • 这时候可能会想到数组,数组允许将多个数据存放到一块。但有一个问题,数组要求每一个构成元素的类型是一样的。这里图书名称、图书作者和出版社可以用字符数组来存储,但图书售价应该用浮点型,出版日期是由整型数字构成吗,ISBN(国际标准书号)通常由 10 位或 13 位数字组成,可以用 long long 类型的变量来存放。

  • 那么为了应对这种情况,C 语言就弄出了个结构体,来自定义所需要用的类型。

Ⅰ结构体的声明

  • 在 C 语言中,可以使用结构体来组织不同类型的数据。
  • 结构体声明是描述结构体组合的主要方法,语法格式为:
struct 结构体名称
{
	结构体成员1;
	结构体成员2;
	结构体成员3;
	......
	结构体成员n;
};
  • 其中,结构体成员既可以是任何一种基本的数据类型,也可以是另一个结构体,如果是后者,那么就相当于结构体的嵌套。
  • 那么,一本书的结构体声明就应该是这样的:
struct Book
{
	char title[128];	//图书名称
	char author[40];	//图书作者
	float price;		//图书价格
	unsigned int date;	//出版日期
	char publisher[40];	//出版社
};						//分号不能丢
  • 这样的话,相当于描绘了一个关于书的框架(数据类型),然后再根据这个框架来定义结构体变量。
  • 注意,这里的 struct 关键字是必不可少的,Book 是这个框架的名称,通常为了与普通变量和宏区分开来,这里约定使用第一个字符为大写的单词,另外末尾的分号也别忘了。
  • 结构体声明既可以放在所有函数的外面,也可以单独放在一个函数里面声明。如果是后者,则结构体只能在函数中被定义。

Ⅱ 结构体的定义

  • 结构体声明只是进行一个框架的描述,定义一个真正的结构体类型变量之前,它并不会在内存中分配空间存储数据。
    • 就像 int double 这些,在使用这些类型定义变量之前,这些类型本身并不会占据内存空间。
  • 定义结构体变量的语法如下:
struct 结构体名称 结构体变量名;
  • 注意:这里的 struct 关键字不能丢

使用结构体类型定义局部变量

  • 声明和定义一起写。
#include <stdio.h>

struct Book
{
	char title[128];	//图书名称
	char author[40];	//图书作者
	float price;		//图书价格
	unsigned int date;	//出版日期
	char publisher[40];	//出版社
};

int main()
{
	struct Book book;
	//book 是使用 struct Book 结构体类型创建的结构体变量
	return 0;
}

使用结构体类型定义全局变量

  • 在结构体声明的时候定义结构体变量。
#include <stdio.h>

struct Book
{
	char title[128];	//图书名称
	char author[40];	//图书作者
	float price;		//图书价格
	unsigned int date;	//出版日期
	char publisher[40];	//出版社
}book1;					//在声明结构体的时候就把 book 变量创建出来

struct Book book2;		

int main()
{
	......

	return 0;
}
  • 如果是这样,那么定义的结构体变量 book1 和 book2 就是一个全局变量,在其他函数中也可以对它进行访问。

声明和定义的区别

在这里插入图片描述

Ⅲ 结构体初始化

  • 在定义变量或数组的时候可以对其进行初始化:
int a = 10;
int arr[] = {1,2,3,4,5};
  • 自然,在定义结构体变量的同时,也能够对其进行初始化。
struct Book book = {"《C primer plus》","史蒂芬·普拉达",108,20160401,"人民邮电出版社"};
  • 和初始化数组一样,用一个大括号把所有成员的值括起来,用逗号作为分隔符。
  • 如果要这样写,注意结构体的各个成员类型要对号入座,顺序不能搞乱(C 语言还没聪明到帮你做这种事)。

Ⅳ 访问结构体成员

⒈结构体变量访问结构体成员

  • 变量访问结构体成员,需要引入点号 “ . ” 运算符
  • 例如,book.title 就是引用 book 结构体的 titile 成员,它是一个字符数组,而 book.price 则是引用 book 结构体的 price 成员。

举个栗子

#include <stdio.h>

struct Book
{
	char title[128];
	char author[40];
	float price;
	unsigned int date;
	char publisher[40];
};

int main()
{
	struct Book book = { "《C primer plus》",
							"史蒂芬·普拉达",
							108,
							20160401,
							"人民邮电出版社" 
						};

	printf("书名:%s\n", book.title);
	printf("作者:%s\n", book.author);
	printf("价格:%.2f\n", book.price);
	printf("出版日期:%u\n", book.date);
	printf("出版社:%s\n", book.publisher);
	
	return 0;
}

在这里插入图片描述

⒉结构体指针访问结构体成员

  • 将定义的结构体变量的地址取出来,赋于结构体指针,让结构体指针来代替结构体变量干活。

定义结构体指针

struct Book book;
struct Book* p = &book;
  • “ * ” 说明了 p 是个指针,struct Book 说明了 p 指向的是个 struct Book 类型的变量。

指针访问结构体成员

  • 指针访问结构体成员,需要引入 “ -> ” 操作符
  • 比如 p -> title 就是引用 p 所指向的结构体的 title 成员。
#include <stdio.h>

struct Book
{
	char title[128];
	char author[40];
	float price;
	unsigned int date;
	char publisher[40];
};

int main()
{
	struct Book book = { "《C primer plus》",
							"史蒂芬·普拉达",
							108,
							20160401,
							"人民邮电出版社"
						};

	struct Book* p = &book;

	printf("书名:%s\n", p->title);
	printf("作者:%s\n", p->author);
	printf("价格:%.2f\n", p->price);
	printf("出版日期:%u\n", p->date);
	printf("出版社:%s\n", p->publisher);

	return 0;
}

在这里插入图片描述

Ⅴ 结构体的嵌套

  • 就像分支语句、循环语句、函数可以嵌套一样,结构体也可以进行嵌套。

举个栗子

  • 结构体嵌套了的话,对结构体体变量进行初始化也要进行嵌套。
  • 对于日期来说,可以单独为其声明一个结构体类型:
struct Date
{
	int year;
	int month;
	int day;
};

struct Book
{
	char title[128];
	char author[40];
	float price;
	struct Date date;
	char publisher[40];	
};

int main()
{
	struct Book book  = {"《C primer plus》",
							"史蒂芬·普拉达",
							108,
							{2016,04,01},
							"人民邮电出版社"
						};

	return 0;
}
  • 这种时候访问结构体成员,就需要使用两层(点号运算符或箭头运算符)
  • 因为 C 语言的结构体,只能对其最底层的成员进行访问,所以如果存在多级结构体嵌套的话,就需要一级一级的深入,直到找到最底层的成员才行。
  • 因此,想访问日期的话,应该使用 book.date.year,而不是 book.date。
......
int main({
	printf("书名:%s\n", book.title);
	printf("作者:%s\n", book.author);
	printf("价格:%.2f\n", book.price);
	printf("出版日期:%d-%d-%d\n", book.date.year,
					book.date.month,book.date.day);
	printf("出版社:%s\n", book.publisher);
	
	return 0;
}

在这里插入图片描述

  • 指针访问也是大同小异,就不过多废话了。

Ⅵ 结构体传参

  • 结构体在进行传参的时候,同样可以选择传结构体变量或传结构体地址

先说结论

  • 结构体传参的时候,要传结构体的地址

举个栗子

#include <stdio.h>

struct Book
{
	char title[128];
	char author[40];
	float price;
	unsigned int date;
	char publisher[40];
};

void print1(struct Book book)
{
	printf("-----传结构体变量-----\n");
	printf("书名:%s\n", book.title);
	printf("作者:%s\n", book.author);
	printf("价格:%.2f\n", book.price);
	printf("出版日期:%u\n", book.date);
	printf("出版社:%s\n",book.publisher);
	printf("----------------------\n");
}

void print2(struct Book* p)
{
	printf("\n-----传结构体地址-----\n");
	printf("书名:%s\n", p->title);
	printf("作者:%s\n", p->author);
	printf("价格:%.2f\n", p->price);
	printf("出版日期:%u\n", p->date);
	printf("出版社:%s\n", p->publisher);
	printf("----------------------\n");
}

int main()
{
	struct Book book = { "《C primer plus》",
							"史蒂芬·普拉达",
							108,
							20160401,
							"人民邮电出版社"
						};

	print1(book); //传结构体变量
	print2(&book);//传结构体地址


	return 0;
}

在这里插入图片描述

上面的 print1 和 print2 哪种更好?

  • 首选 print2 函数。
  • 原因:
    • 函数传参的时候,参数是需要压栈的。
    • 如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

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

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

相关文章

基于R语言的水文、水环境模型优化技术及快速率定方法与多模型案例实践

目录 专题一、最速上升法、岭分析以及响应曲面模型 专题二、Kriging插值与优化方法 专题三、启发式算法 专题四、采样方法 专题五、高斯过程回归 专题六、基于模型的高斯过程/贝叶斯优化设计 专题七、最优化的快速化 专题八、高级高斯过程模型 专题九、异方差性 专题…

动手学深度学习——图像分类数据集(代码详解)

目录 1. 图像分类数据集1.1 读取数据集1.2 读取小批量1.3 整合所有组件1.4 小结 1. 图像分类数据集 这里采用Fashion-MNIST数据集 torchvision&#xff1a;torch类型的可视化包&#xff0c;一般计算机视觉和数据可视化需要使用from torchvision import transforms&#xff1a;…

基于单片机的智能台灯 灯光控制系统人体感应楼梯灯系统的设计与实现

功能介绍 以STM32单片机作为主控系统&#xff1b;主通过光敏采集当前光线强度&#xff1b;通过PMW灯光调节电路&#xff0c;我们可以根据不同的光线亮度&#xff0c;进行3挡调节&#xff1b;通过人体红外检测当前是否有人&#xff1b;通过不同光线情况下使用PWM脉冲电路进行调节…

13matlab数据分析多项式的求值(matlab程序)

1.简述 统计分析常用函数 求最大值 max 和 sum 积 prod 平均值&#xff1a;mean 累加和&#xff1a;cumsum 标准差&#xff1a;std 方差&#xff1a;var 相关系数&#xff1a;corrcoef 排序&#xff1a;sort 四则运算 1.多项式的加减运算就是所对应的系数向量的加减运算&#…

使用jQuery的ajax提交图片信息

1 设置图片id&#xff08;html&#xff09; 首先&#xff0c;定义上传图片的id&#xff0c;根据上传文件的id获取图片信息&#xff1a; 注&#xff1a;图片的id应该设置在input标签里面 2 发送ajax请求&#xff08;js&#xff09; var formData new FormData(); formData.ap…

day40-Mybatis(resultMap拓展)

0目录 Mybatis-resultMap拓展 1.2.3 1.数据库字段和javabean实体类属性不一致时 解决方案1&#xff1a;将sql语句中给予别名&#xff08;别名同javabean中实体类保持一致&#xff09; 解决方案2&#xff1a;使用resultMap 2.两表关联&#xff08;用户表和角色表关联查询&…

【算法基础:数据结构】2.2 字典树/前缀树 Trie

文章目录 知识点cpp结构体模板 模板例题835. Trie字符串统计❤️❤️❤️❤️❤️&#xff08;重要&#xff01;模板&#xff01;&#xff09;143. 最大异或对&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#x1f62d;&#xff08;Trie树的应用&#xff09; 相关题目…

【UE4 塔防游戏系列】06-炮塔发射子弹攻击敌人

效果 步骤 1. 新建一个Actor蓝图类&#xff0c;命名为“TotalBulletsCategory”&#xff0c;用来表示子弹蓝图总类&#xff0c;后面会有很多不同类型的子弹会继承该类 打开“TotalBulletsCategory”&#xff0c;添加粒子系统组件、盒体碰撞组件和发射物移动组件 调整发射物重力…

电压放大器在超声波焊接中的作用以及应用

电压放大器是一种运用于电子设备中的信号放大器&#xff0c;主要作用是将小信号放大为更高幅度的信号。在超声波焊接中&#xff0c;电压放大器起到了重要的作用&#xff0c;它可以将从传感器采集到的微小信号放大为能够被检测和处理的合适大小的信号。 超声波焊接是现代工业生产…

使用shell监控应用运行状态通过企业微信接收监控通知

目的&#xff1a;编写shell脚本来监控应用服务运行状态&#xff0c;若是应用异常则自动重启应用通过企业微信接收监控告警通知 知识要点&#xff1a; 使用shell脚本监控应用服务使用shell脚本自动恢复异常服务通过企业微信通知接收监控结果shell脚本使用数组知识&#xff0c;…

二次元少女-InsCode Stable Diffusion 美图活动一期

一、 Stable Diffusion 模型在线使用地址&#xff1a; https://inscode.csdn.net/inscode/Stable-Diffusion 二、模型相关版本和参数配置&#xff1a; 模型版本&#xff1a;chilloutmix_NiPrunedFp32Fix.safetensors 采样方法(Sampler)Sampling method&#xff1a;DPM SDE …

xpath下载安装——Python爬虫xpath插件下载安装(2023.7亲测可用!!)

目录 1.免费下载插件链接&#xff08;若失效评论区留言发送最新链接&#xff09;&#xff08;2023.7亲测可用&#xff09; 2.安装插件 &#xff08;1&#xff09;打开chrome浏览器页面&#xff0c;点击&#xff1a;右上角三个点 > 扩展程序 > 管理拓展程序 &#xff…

2023-7-19-第二十式迭代器模式

&#x1f37f;*★,*:.☆(&#xffe3;▽&#xffe3;)/$:*.★* &#x1f37f; &#x1f4a5;&#x1f4a5;&#x1f4a5;欢迎来到&#x1f91e;汤姆&#x1f91e;的csdn博文&#x1f4a5;&#x1f4a5;&#x1f4a5; &#x1f49f;&#x1f49f;喜欢的朋友可以关注一下&#xf…

TortoiseGit 入门指南12:创建标签

前面的文章不止一次的提到过 标签 &#xff08;Tag&#xff09;&#xff0c;我们在《TortoiseGit 入门指南08&#xff1a;浏览引用以及在引用间切换》一文中知道&#xff0c;标签 是一种 引用&#xff1b;还知道每个提交都对应着一个 SHA-1 值&#xff0c;而引用就是 SHA-1 的一…

SuperGlue学习记录之最优传输

在进行最优传输相关理论的学习过程中&#xff0c;找到SuperGlue这篇论文&#xff0c;该篇论文通过最优传输来完成特征点的匹配过程。 SuperGlue结构 先来看一下其结构&#xff1a; 首先将两张图片送入特征提取网络&#xff0c;通过卷积网络提取出特征&#xff0c;主要有四个值…

Generative Adversarial Network

Goodfellow,2014年 文献阅读笔记--GAN--Generative Adversarial NetworkGAN的原始论文-组会讲解_gan英文论文_Flying Warrior的博客-CSDN博客 启发:如何看两个数据是否来自同一个分布? 在统计中,two sample test。训练一个二分类的分类器,如果能分开这两个数据,说明来自…

网络安全—信息安全—黑客技术(学习笔记)

一、什么是网络安全&#xff1f; 网络安全可以基于攻击和防御视角来分类&#xff0c;我们经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”则研究防御技术。 无论网络、Web、移动、桌面、云等哪个领域&#xff0c;都…

[深度学习入门]什么是神经网络?[神经网络的架构、工作、激活函数]

目录 一、前言二、神经网络的架构——以手写数字识别三、神经网络的工作1、单输入单输出感知器函数2、二维输入参数3、三维输入参数 四、激活函数1、激活函数2、ReLU激活函数3、非线性激活函数&#xff08;1&#xff09;二输入二输出的神经网络的架构&#xff08;2&#xff09;…

计算机网络 day8 动态路由 - NAT - SNAT实验 - VMware的网卡的3种模式

目录 动态路由&#xff1a;IGP 和 EGP 参考网课&#xff1a;4.6.1 路由选择协议概述_哔哩哔哩_bilibili ​编辑 IGP&#xff08;Interior Gateway Protocol&#xff09;内部网关协议&#xff1a; EGP&#xff08;Interior Gateway Protocol&#xff09;外部网关协议&#x…

使用模板创建【vite+vue3+ts】项目出现 “找不到模块‘vue‘或其相应的类型声明” 的解决方案

问题描述 项目前台需要使用Vue3Ts来写一个H5应用&#xff0c;然后我用模板创建 npm create vitelatest vue3-vant-mobile -- --template vue-ts创建完后进入HelloWorld.vue&#xff0c;两眼一黑 解决办法一 npm i --save-dev types/node然后在tsconfig.json的"compi…