C语言--结构体初阶

news2024/9/24 9:19:21

目录

  • 前言
  • 结构体类型的声明
    • 什么是结构
    • 结构的声明
    • 结构体变量的定义
    • 结构成员的类型
    • 结构体变量的初始化
  • 结构体的成员访问
  • 结构体传参
    • 函数调用的参数压栈

前言

在前面的C语言学习中,我们学习了形如char,short,int,float等的不同类型的变量,但是当我们要描述一个人的时候,我们发现单靠其中的某一种类型的变量很难完整的描述出一个人来,人有年龄,性别,身高,身份证编号等等的信息,所以人是一个复杂的对象,这时我们就要引出结构体类型,它可以把要描述的对象的不同信息放到里面去

结构体类型的声明

什么是结构

结构是一些值的集合,这些值称为成员变量。结构体的每个成员可以是不同类型的变量。
到目前为止,我们学习的数组也是一个集合,数组是一组相同元素的集合。而结构体也是一些值的集合,但是这些值的类型可以不同

结构的声明

结构的声明框架如下

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

假设我们要来定义一个人,看下面这段代码

struct Stu
{
	//成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
};

注意,在这段代码的最后有一个分号,这是因为结构体类型也是一种类型,类比于int类型,我们在对int类型进行声明的时候最后也会用到分号,如图1.
图1

结构体变量的定义

有了结构体类型,那如何定义变量,其实很简单。
我们来创建一个对象 s

struct Stu
{
	//成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
};

int main()
{
	struct Stu s;//对象
	return 0;
}

这段代码我们通过类型创建了一个对象出来,这就和现实生活中的通过图纸来造一个房子很类似,类型中有我们对这个对象的描述,而图纸中也有我们对房子的描述,客厅,厨房的位置等等。

我们现在反回去看结构体的声明框架,发现在大括号外还可以定义变量,如下面这段代码的s1,s2

struct Stu
{
	//成员变量
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
}s1,s2;

int main()
{
	struct Stu s;//对象
	return 0;
}

这里的s1和s2也是结构体变量,只不过和s不同的是,s1,s2是全局变量,而s是局部变量

结构成员的类型

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

看下面这段代码

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
}s1,s2;

在Stu这个结构体里面就有一个结构体成员sb。

结构体变量的初始化

类比数组的初始化,数组的初始化使用到了大括号,结构体变量的初始化也是用的大括号,然后我们只用按照结构体内的成员变量类型挨个进行初始化即可。如下面这段代码

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
}s1,s2;

int main()
{
	struct Stu s = {{'w',20,3,14},"张三",30,"51192430020987"};
	return 0;
}

成员变量有结构体,就再用一个大括号对这个结构体初始化即可。
在对s初始化的时候我们同样可以对s1,s2初始化,这就叫做结构体的嵌套初始化

struct Stu        //类型声明
{
 char name[15];//名字
 int age;      //年龄
};
struct Stu s = {"zhangsan", 20};//初始化
struct Node
{
 int data;
 struct Point p;
 struct Node* next; 
}n1 = {10, {4,5}, NULL}; //结构体嵌套初始化
struct Node n2 = {20, {5, 6}, NULL};//结构体嵌套初始化

结构体的成员访问

结构变量的成员是通过点操作符(.)和箭头操作符(->)访问的。点操作符接受两个操作数。

struct B
{
	char c;
	short s;
	double d;
};
struct Stu
{
	//成员变量
	struct B sb;
	char name[20];//名字
	int age;//年龄
	char id[20];//身份证号
}s1,s2;

int main()
{
	struct Stu s = { {'w',20,3.14},"张三",30,"51192430020987" };
	printf("%c\n", s.sb.c);

	struct Stu* ps = &s;
	printf("%c\n",(*ps).sb.c);
	printf("%c\n", ps->sb.c);
	return 0;
}

代码运行结果如图2
图2
我们不难发现,(*ps).sb.c和ps->sb.c是等价的

结构体传参

我们在实现某些代码的时候,这个代码我们可能不会立马就要处理,可能要传给一个函数进行处理。
我们假设要写一个函数来打印s,看下面这段代码

void print1(struct Stu t)
{
	printf("%c %d %lf %s %d %s\n", t.sb.c, t.sb.s, t.sb.d, t.name, t.age, t.id);
}
int main()
{
	struct Stu s = { {'w',20,3.14},"张三",30,"51192430020987" };
	print1(s);
	return 0;
}

代码运行结果如图3
图3
我们在函数传参的学习中,学过两种调用方法:传值调用和传址调用。上面代码实现的是传值调用,我们再来写一段代码实现传址调用

void print2(struct Stu* t)
{
	printf("%c %d %lf %s %d %s\n", t->sb.c, t->sb.s, t->sb.d, t->name, t->age, t->id);
}
int main()
{
	struct Stu s = { {'w',20,3.14},"张三",30,"51192430020987" };
	print2(&s);
	return 0;
}

代码运行结果如图4
图4
那么在两种方法都能实现的情况下,是传值调用好呢还是传址调用好?
在前面的学习中,我们知道,传址调用要高效的多。传址调用中,形参要接收传递过来的实参,还得创建一个空间t,那么s有多大,t就有多大。而且·传递这么多数据还会花费一定的时间,在空间和时间上都有较大的浪费但是,如果我们传递的是地址,地址就只有4/8个字节,那么空间开辟就大大减少,而且如果是值传递,t只是s的一份临时拷贝,改变t的值并不会影响到s,而如果将地址传递过去,我们可以直接通过地址找到s,从而能直接修改s的数据,功能性更强一些
还有一方面的原因:
函数传参的时候,参数是需要压栈的。
如果传递一个结构体对象的时候,结构体过大,参数压栈的的系统开销比较大,所以会导致性能的下降。

函数调用的参数压栈

什么是压栈呢?
栈是一种数据结构,先进后出,后进先出(类似于装子弹),如图5
图5
传参的时候也是类似,看下面这段代码

int Add(int x, int y)
{
	int z = 0;
	z = x + y;
	return z;
}//每一个函数调用都会在内存的栈区上开辟一块空间

int main()
{
	int a = 3;
	int b = 5;
	int c = 0;
	c = Add(a, b);
	return 0;
}

栈区 如图6
图6
从图中我们可以看出,如果是传值调用,参数压栈的开销就会比较大,性能就会下降。

以上就是对结构体类型的讲解,如有出入,欢迎指正。

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

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

相关文章

活动星投票臻我风采评选视频投票的功能在线投票程序

“臻我风采评选”网络评选投票_线上小程序的投票方式_视频投票的功能_在线投票程序用户在使用微信投票的时候,需要功能齐全,又快捷方便的投票小程序。而“活动星投票”这款软件使用非常的方便,用户可以随时使用手机微信小程序获得线上投票服务…

即时通讯开发之详解TCP/IP中的IP选路、动态选路

静态 IP 选路 1一个简单的路由表 选路是 IP 层最重要的一个功能之一。前面的部分已经简单的讲过路由器是通过何种规则来根据 IP 数据包的 IP 地址来选择路由。 这里就不重复了。 对于一个给定的路由器,可以打印出五种不同的 flag:  U 表明该路由可用。  G…

Qlik Sense Enterprise Windows版(非集群)——详细安装步骤

Qlik Sense分为客户端(Desktop)和服务器(Server),本文主要介绍Qlik Sense Server的图形化界面安装操作。 安装方式也分为两种,一种是图形化界面安装,另一种是静默安装。一般只有在特殊报错情况下我们才使用静默安装,静默安装的方…

实现分页查询

实现分页查询一、分页要素与语法二、例:博客系统文章列表页2.1 原始前端代码2.2 实现:查询分页数据验证2.3 实现 “首页” “上一页” “下一页” “末页”前端代码添加得到总页数实现 四个点击效果验证一、分页要素与语法 分页要素: 1&…

Qt音视频开发13-视频解码线程基类的设计

一、前言 这个解码线程基类的设计,是到目前为止个人觉得自己设计的最好的基类之一,当然也不是一开始就知道这样设计,没有个三五年的摸爬滚打以及社会的毒打,是想不到要这样设计的,一方面是要不断提炼各种视频类视频组…

伪逆矩阵 的使用

伪逆矩阵(pseudo-inverse)_Uglyduckling911的博客-CSDN博客_伪逆矩阵 一、什么是伪逆矩阵 若任意矩阵Am*n,B 为A的广义逆矩阵,若B满足下述条件(Moore-penrose条件): (1)BAB B&am…

4.门面模式,组合模式,享元模式

门面模式 为了保证接口的可复用性(或者叫通用性),我们需要将接口尽量设计得细粒度一点,职责单一一点。但是,如果接口的粒度过小,在接口的使用者开发一个业务功能时,就会导致需要调用 n 多细粒度…

【手把手】教你使用JMH和Disruptor - 多线程与高并发工具

JMH JMH全称是Java Microbenchmark Harness(Java微基准测试),简单讲其实就是测一个方法的性能好坏。这个测试的框架是2013年发出来的,由JLT的开发人员开发,后来归到了OpenJDK下面,官网地址:htt…

运维实践 | OpenMLDB 跨机房容灾方案

背景 在单集群部署环境下,OpenMLDB 具备集群内节点级别的高可用能力。但若受到机房断电或者自然灾害等不可抗拒因素,则将造成的机房或大部分节点无法正常运转的情况,从而引发该集群状态异常,导致在线服务中断。为此,Op…

悉数美剧《黑客军团》中的黑客工具

本篇文章中主要列举《Mr. Robot》电视剧中主要用到的黑客工具,并对它们所对应的现实中的黑客工具做一简要介绍。Mr. Robot2015年美剧出了一部关于黑客题材的电视剧,相信爱看黑客电视剧、电影的同学们已经看过或者正在追这部神秘的《Mr. Robot》&#xff…

零基础学MySQL(四)-- 数据库最常用的操作【查询基础篇 -- 单表查询】

目录📔一、最简单的 select 语句1️⃣基本语法2️⃣基本练习3️⃣补充说明(1) 使用表达式对查询的列进行运算(2) 在 select 语句中可使用 as 语句取别名📕二、使用 where 子句进行过滤查询1️⃣基本语法2️⃣在 where 子句中经常使用的运算符3️⃣基本练…

4道面试题让你了解 ThreadLocal 的那点小秘密

我收集了4个面试中出现频率较高的关于ThreadLocal的问题: 什么是ThreadLocal?什么场景下使用ThreadLocal?ThreadLocal的底层是如何实现的?ThreadLocal在什么情况下会出现内存泄漏?使用ThreadLocal要注意哪些内容&…

工赋开发者社区 | 事件驱动架构要避开的 5 个陷阱

事件驱动架构非常强大,非常适合用在分布式微服务环境中。事件驱动架构提供了解耦的架构、更容易实现的可伸缩性和更高程度的弹性。请求应答(客户端和服务器)与事件流(发布和订阅)但是,与请求和应答类型的架…

防范DDOS攻击的最佳方法

Botnets是由多个感染的计算机(称为"bots"或"zombies")组成的网络。这些感染的计算机受到攻击者的控制,可以同时发送大量的数据流量到目标网站,导致DDoS(分布式拒绝服务)攻击。Botnets也可以用于从感染的计算机中获取私人信息,传播病毒和蠕虫,或者执…

Git使用个人访问令牌提交代码到仓库

文章目录前言解决方法1、创建自己的token2.1、使用token(classic)2.2、使用token(方法二)参考链接前言 2021年8月13日开始,GitHub在使用Git操作远程仓库时不再支持使用用户名密码形式进行身份验证,需使用个人访问令牌。 使用Git操作GitHub仓库时使用用户…

整合spring cloud云服务架构 - 企业分布式微服务云架构构建

1. 介绍 Commonservice-system是一个大型分布式、微服务、面向企业的JavaEE体系快速研发平台,基于模块化、服务化、原子化、热插拔的设计思想,使用成熟领先的无商业限制的主流开源技术构建。采用服务化的组件开发模式,可实现复杂的业务功能。…

电脑开不了机怎么办?排查这3种情况

电脑开不了机不一定是电脑故障损坏的问题,也可能是硬件或者是线路松动导致的。电脑开不了机的原因有很多,电脑开不了机怎么办?我们先来了解下主要是哪些原因,排查出原因才好对症下药。 操作环境: 演示机型:…

Leetcode刷题注意点

时间复杂度:一个句子被执行多少次。 空间复杂度:一个算法在运行过程中临时占用存储空间大小的量度 列表可以用.append() 添加数据 字符串 用 s q 这个写法。 03 此题关键是哈希表的运用。 dic set() 表示取出nums中的key 并且set里面元素不重复 53…

python多光谱遥感数据处理、图像分类、定量评估及机器学习方法应用

普通数码相机记录了红、绿、蓝三种波长的光,多光谱成像技术除了记录这三种波长光之外,还可以记录其他波长(例如:近红外、热红外等)光的信息。与昂贵、不易获取的高光谱、高空间分辨率卫星数据相比,中等分辨…

2023年广州Java培训机构排行榜来啦,快来围观!

到底哪个Java培训机构靠谱?Java培训怎么选?如何在千万培训机构中一眼寻觅到自己的唯一所爱?别疑惑,别迷茫,小编带着2023最新数据来了,保证你看完有“山重水复疑无路,柳暗花明又一村”的豁然开朗感&#xf…