C语言 底层逻辑详细阐述结构体 #结构体的声明 #结构体的初始化 #结构体成员访问 #结构体传参

文章目录

前言

一、结构体的基础知识

二、结构体的初始化

1、结构体类型声明:

2、结构体成员的类型

3、结构体变量的初始化:

三、结构体成员访问 

四、结构体传参

总结


前言

基于自我理解的角度来讲结构体;


一、结构体的基础知识

结构是一些值的集合,这些值称为成员变量;结构的每个成员可以是不同类型的变量;

注:数组是相同元素的集合;而结构体中可以放不同类型的数据,例如想要做一个表达一个复杂对象的数据;比如说是描述一个人,就得说这个人的姓名、年龄,性别、身高、电话等,想要准确存储这些信息就得使用不同的变量,把这些不同类型的变量整合在另个一变量中,便就是结构体变量;

二、结构体的初始化

当我们想要初始化一个整型变量,int a = 4; --> 需要变量的类型+变量名+ 初始化的值;

所以首先我们要声明其类型:

1、结构体类型声明:

下图是结构体类型声明的模板:

其中 struct tag 是结构体的类型,stract 不可以更改,tag 可以更改;number-list  就是成员列表; variable-list 是变量列表,在声明的过程中可要可不要; 列表就是不止一个的意思;

方式一:声明时省略variable-list(通常是这样的方式) :

这里就仅仅声明了一个结构体类型

方式二:声明时不省略variable-list :

利用结构体类型创建了变量p1、p2 , 此处的结构体类型用来描述一个人的信息,那么p1、p2 也可以理解为被描述的两个人;

其中p1、p2 为全局的结构体变量(一般不推荐用全局变量),这也就是不常用此方法的原因。

注:结构体类型的声明通常是在main函数外进行的;当然也可以在主函数内部进行声明,只不过此时的结构体类型就为局部变量,只能在main 函数的内部使用;此处并不是全局变量与局部变量,请注意。

重点分析:在对结构体类型进行声明的时候,并不会向内存申请空间;当只有创建一个变量时才会向内存申请空间;可以将结构体类型当作建房子的图纸,图纸并会占据你要建房地基的空间,只有当你真正意义上开始建房子(创建变量)的时候,才会占据空间;同理。

2、结构体成员的类型

结构体成员可以是标量、数组、指针,甚至是其他结构体

代码如下:

#include<stdio.h>struct Peo
{char name[20];int age;char sex[10];int high;char tel[10];struct home s;
};
}p5; struct home
{char name[20];int age;char sex[10];
};struct Peo p2,p3,p4;  //结构体变量的创建int main()
{struct Peo p1; //结构体变量的创建return 0;
}

其中p1为局部变量,p2、p3、p4为全局变量,同时p5 也是全局变量;结构体成员的类型可以是标量、数组、指针、结构体;

3、结构体变量的初始化:

在结构体变量创建时再给它一个初始值就是结构体变量的初始化。

注:在创建结构体变量赋值时,至少为一个结构体成员赋值;故而分为完全初始化与不完全初始化;

代码如下:

#include<stdio.h>
struct Peo
{char name[20];int age;char sex[10];int high;char tel[20];
}p1,p2;int main()
{struct Peo p1 = { "zhangsan",19,"保密",180,"123456789" };return 0;
}

而若是对结构体中成员是结构体的这种情况是该如何初始化呢?

代码如下:

#include<stdio.h>struct home
{char name[20];int age;char sex[10];
};struct Peo
{char name[20];int age;char sex[10];int high;char tel[10];struct home s;
};int main()
{struct Peo p1 = { "zhangsan",19,"保密",185,"1234567",{"lisi",11,"女"} };return 0;
}

如上,按照所创建变量的类型,按照类型声明时的顺序进行初始化就行,成员之间的数据用 ' , ' 隔开,如果遇到结构体的成员中有结构体,就将另一结构体的数据放入 { } 中,结构体的成员中的结构体的成员之间的数据也是用 ' , ' 隔开。

同理,在数组中若初始化时的数据个数小于数组元素的个数,那么就存在未初始化的数组元素,这就是未完全初始化;请看一下代码:

#include<stdio.h>struct home
{char name[20];int age;char sex[10];
};struct Peo
{char name[20];int age;char sex[10];int high;char tel[10];struct home s;
};int main()
{struct Peo p1 = { "zhangsan",19,"保密",185,"1234567",{"lisi"} };return 0;
}

代码调试结果如下:

分析:可以发现,我们此处未对 struct home s 中后两个成员进行赋值;在数组中,初始化时未被赋值的元素会默认为 ’\0‘ (因 '\0' 的ASCII码值为0,故而可以将 '\0' 就当作0);对结构体变量进行初始化本质上是对结构体中的成员进行初始化,而其成员就是我们平时接触的内置类型、数组(无非其成员可能会是结构体变量,本质上就是嵌套结构体,一层一层进行赋值即可),若是结构体变量未初始化相对应的内置类型表现为随机值,而数组就是 ’\0‘;

三、结构体成员访问 

会用到两个操作符 . 点操作符  -> 箭头操作符

二者访问结构体变量成员的运用:

. 点操作符: 结构体变量 . 成员名  

-> 箭头操作符 : 结构体变量指针 -> 成员名

注:结构体变量 = * 结构体变量指针,故而存在 ( * 结构体变量指针 ). 成员名

以下代码将展示这三种结构体成员的访问:

代码如下:

#include<stdio.h>struct home
{char name[20];int age;char sex[10];
};struct Peo
{char name[20];int age;char sex[10];int high;char tel[10];struct home s;
};void print(struct Peo* s)
{printf("%s %d %s %d %s %s %d %s\n", (*s).name, (*s).age, (*s).sex, (*s).high, (*s).tel, (*s).name, (*s).age, (*s).sex);printf("%s %d %s %d %s %s %d %s\n", s->name, s->age, s->sex, s->high, s->tel, s->name, s->age, s->sex);
}int main()
{struct Peo p = { "zhangsan",19,"保密",185,"1234567",{"lisi",11,"保密"}};printf("%s %d %s %d %s %s %d %s\n", p.name, p.age, p.sex, p.high, p.tel, p.name, p.age, p.sex);print(&p);return 0;
}

代码运行结果如下:

四、结构体传参

在学习函数的时候,我们知道有传值传参和传址传参

传值传参,形参是对实参的一份临时拷贝;传址传参就是将其变量的地址传过去,即对存在内存中的数据进行操作;结构体变量也存在传值传参和传址传参,且道理与函数传参相同;

我们来看一下这两种传参方式的例子:

代码如下:

#include<stdio.h>struct Peo
{char name[10];
};void print1(struct Peo ps)
{printf("%s\n", ps.name);
}
void print2(struct Peo* s)
{printf("%s\n", s->name);
}int main()
{struct Peo p = { "zhangsan" };print1(p);//传值传参print2(&p); //传址传参return 0;
}

代码运行结果如下::

思考:若是讨论传参用来打印的话,传址传参比传值传参更好,因为如果结构体对象很大即其所占的空间很大,那么传值传参就会浪费空间来进行拷贝,并且在拷贝的时候也会废时,这就会导致其性能降低;

当实参进行传值传参时,形参是对实参的一份临时拷贝,此时形参会在栈帧(即为本次 printf() 所开辟于函数栈帧中找的空间) 中存放 ;若结构体在内存空间中所占的空间很大,栈帧就会因形参的拷贝而增大,于是乎就浪费了很多空间;

专业描述原因:

1、函数传参时,参数需要压栈,会有时间和空间上的开销;

2、如果传递的一个结构体变量,其在空间中所占的内存很大时,参数压栈的系统开销比较大,所以会导致性能的下降;

所以:结构体传参时,最好传其地址


总结

1、结构是一些值的集合,这些值称为成员变量;结构的每个成员可以是不同类型的变量;

2、结构体类型的声明通常是在main函数外进行的;当然也可以在主函数内部进行声明,只不过此时的结构体类型就为局部变量,只能在main 函数的内部使用;此处并不是全局变量与局部变量,请注意。

3、在结构体变量创建时再给它一个初始值就是结构体变量的初始化;在创建结构体变量赋值时,至少为一个结构体成员赋值;故而分为完全初始化与不完全初始化;

4、. 点操作符: 结构体变量 . 成员名  

-> 箭头操作符 : 结构体变量指针 -> 成员名

注:结构体变量 = * 结构体变量指针,故而存在 ( * 结构体变量指针 ). 成员名

5、函数传参时,参数需要压栈,会有时间和空间上的开销;如果传递的一个结构体变量,其在空间中所占的内存很大时,参数压栈的系统开销比较大,所以会导致性能的下降;

所以:结构体传参时,最好传其地址;

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

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

相关文章

NSSCTF中24网安培训day2中web题目

[SWPUCTF 2021 新生赛]ez_unserialize 这道题目考察php反序列化的知识点 打开题目&#xff0c;发现没有提示&#xff0c;我们试着用御剑扫描目录文件&#xff0c;发现存在robots.txt的文件 接着访问这个文件&#xff0c;发现是一段php反序列化代码&#xff0c;我们需要进行序…

论文翻译:通过云计算对联网多智能体系统进行预测控制

通过云计算对联网多智能体系统进行预测控制 文章目录 通过云计算对联网多智能体系统进行预测控制摘要前言通过云计算实现联网的多智能体控制系统网络化多智能体系统的云预测控制器设计云预测控制系统的稳定性和一致性分析例子结论 摘要 本文研究了基于云计算的网络化多智能体预…

【常见开源库的二次开发】基于openssl的加密与解密——Base58比特币钱包地址——算法分析(三)

目录&#xff1a; 目录&#xff1a; 一、base58(58进制) 1.1 什么是base58&#xff1f; 1.2 辗转相除法 1.3 base58输出字节数&#xff1a; 二、源码分析&#xff1a; 2.1源代码&#xff1a; 2.2 算法思路介绍&#xff1a; 2.2.1 Base58编码过程&#xff1a; 2.1.2 Base58解码过…

Leetcode—146. LRU 缓存【中等】(shared_ptr、unordered_map、list)

2024每日刷题&#xff08;143&#xff09; Leetcode—146. LRU 缓存 先验知识 list & unordered_map 实现代码 struct Node{int key;int value;Node(int key, int value): key(key), value(value) {} };class LRUCache { public:LRUCache(int capacity): m_capacity(capa…

实战案例:用百度千帆大模型API开发智能五子棋

前随着人工智能技术的迅猛发展&#xff0c;各种智能应用层出不穷。五子棋作为一款经典的棋类游戏&#xff0c;拥有广泛的爱好者。将人工智能技术与五子棋结合&#xff0c;不仅能提升游戏的趣味性和挑战性&#xff0c;还能展现AI在复杂决策问题上的强大能力。在本篇文章中&#…

habase集群安装

解压到/opt/softs目录 tar -zxvf hbase-2.4.11-bin.tar.gz -C /opt/softs/ 改名 mv hbase-2.4.11/ hbase2.4.11 配置环境变量 修改/etc/profile vim /etc/profile 添加 #HBASE_HOME export HBASE_HOME/opt/softs/hbase2.4.11 export PATH$PATH:$HBASE_HOME/bin 修改其中的…

怎么把自己写的组件发布到npm官方仓库??

一.注册npm账号 npm官网 1.注册npm 账号 2.登陆 3.登陆成功 二.搭建一个vue 项目 具体步骤参考liu.z Z 博客 或者初始化一个vue项目 vue create XXX &#xff08;工程名字&#xff09;运行代码 npm run serve三.组件封装 1.在src文件下建一个package文件&#xff0…

借助 Aspose.Words,在 C# 中将 Word 转换为 JPG

有时我们需要将 Word 文档转换为图片&#xff0c;因为 DOC 或 DOCX 文件在不同设备上的显示可能会有所不同&#xff0c;但图像&#xff08;例如 JPG 格式&#xff09;在任何地方看起来都一样。 Aspose.Words 是一种高级Word文档处理API&#xff0c;用于执行各种文档管理和操作…

【OrangePi AIpro】: 探索AI加成的开源硬件魅力

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 Orange Pi: 探索开源硬件的魅力引言Orange Pi概述OrangePi AIPro产品介绍试用体…

—张pdf怎么分割成多页,怎么把一个pdf分割

在数字化时代&#xff0c;pdf文件已经成为我们工作和生活中不可或缺的一部分。然而&#xff0c;有时候我们可能会遇到需要将一张pdf文件分割成多页的情况。无论是为了便于分享&#xff0c;还是为了满足特定的文档格式要求&#xff0c;这个任务都可能变得相当棘手。但别担心&…

zookeeper+kafka消息队列群集部署

一、消息队列 1.消息队列 消息是应用间传送的数据 消息队列是应用见的通信方式&#xff0c;消息发送后立即返回&#xff0c;由消息系统确保消息可靠传递。消息发布者只管把消息发布到 MQ 中而不用管谁来取&#xff0c;消息使用者只管从 MQ 中取消息而不管是谁发布的。这样发…

设计模式学习(二)工厂模式——抽象工厂模式+注册表

设计模式学习&#xff08;二&#xff09;工厂模式——抽象工厂模式注册表 前言使用简单工厂改进使用注册表改进参考文章 前言 在上一篇文章中我们提到了抽象工厂模式初版代码的一些缺点&#xff1a;①客户端违反开闭原则②提供方违反开闭原则。本文将针对这两点进行讨论 使用…

CSS-0_3 CSS和单位

文章目录 CSS的值和单位属性值长度单位CSS和绝对单位CSS和相对单位百分比em & rem视口 颜色单位 碎碎念 CSS的值和单位 我们知道&#xff0c;CSS是由属性和属性值所组成的表 随着CSS的发展&#xff0c;属性不说几千也有几百&#xff0c;我从来不支持去背诵所有的可能性。…

昇思25天学习打卡营第22天|基于MindSpore的红酒分类实验

基于MindSpore的红酒分类实验 K近邻算法实现红酒聚类 1、实验目的 了解KNN的基本概念&#xff1b;了解如何使用MindSpore进行KNN实验。 2、K近邻算法原理介绍 K近邻算法&#xff08;K-Nearest-Neighbor, KNN&#xff09;是一种用于分类和回归的非参数统计方法&#xff0c;…

WPF 手撸插件 一

1、本文主要使不适用第三方工具&#xff0c;纯手工的WPF主项目加载另一个WPF的项目&#xff0c;这里我们加载的是*.exe。 2、项目结构如下图。AbstractionLayer用于创建插件的接口。WPFIPluginDemo是主程序。WpfPlugin3是要加载的插件程序。 3、 AbstractionLayer中添加接口IP…

jvm常用密令、jvm性能优化、jvm性能检测、Java jstat密令使用、Java自带工具、Java jmap使用

1.jps是Java虚拟机的进程状态工具&#xff0c;用于列出正在运行的Java进程 jps命令的使用&#xff1a;cmd打开直接jps 1.1不带参数&#xff1a; jps 默认情况下&#xff0c;列出所有正在运行的 Java 进程的进程 ID 和主类名。 1.2 -l&#xff1a;显示完整的主类名或 JAR 文件…

计算机的错误计算(三十二)

摘要 在计算机的错误计算&#xff08;二十八&#xff09;与&#xff08;三十 一&#xff09;中&#xff0c;我们探讨了 Visual Studio 对 6个随机exp(x)函数的计算精度问题。根据网友的反馈&#xff0c;本节将展示 Python 对它们的输出&#xff1a;结果几乎与 Visual Studio …

MyBatis框架学习笔记(四):动态SQL语句、映射关系和缓存

1 动态 SQL 语句-更复杂的查询业务需求 1.1 动态 SQL-官方文档 &#xff08;1&#xff09;文档地址: mybatis – MyBatis 3 | 动态 SQL &#xff08;2&#xff09;为什么需要动态 SQL 动态 SQL 是 MyBatis 的强大特性之一 使用 JDBC 或其它类似的框架&#xff0c;根据不同条…

链接追踪系列-09.spring cloud项目整合elk显示业务日志

准备工作&#xff1a; 参看本系列之前篇&#xff1a;服务器安装elastic search 本机docker启动的kibana-tencent 使用本机安装的logstash。。。 本微服务实现的logstash配置如下&#xff1a; 使用腾讯云redis 启动本机mysql 启动本机docker 启动nacos,微服务依赖它作为…

为什么要使用加密软件?

一、保护数据安全&#xff1a;加密软件通过复杂的加密算法对敏感数据进行加密处理&#xff0c;使得未经授权的人员即使获取了加密数据&#xff0c;也无法轻易解密和获取其中的内容。这极大地提高了数据在存储、传输和使用过程中的安全性。 二、遵守法律法规&#xff1a;在许多国…