C语言学习笔记---结构体初阶

news2024/12/23 6:51:17

C语言程序设计笔记---014

  • C语言结构体初阶
    • 1、结构的基础与概念
      • 1.1、结构体基础例程1 --- 描述一个学生属性
    • 2、结构体成员的类型
      • 2.1、结构体类型例程1 --- 描述一个学生属性
    • 3、结构体的变量定义与初识化
      • 3.1、结构体的变量定义与初识化例程1
      • 3.2、结构体的变量定义与初识化例程2
    • 4、结构体成员的访问
      • 4.1、结构体成员的访问例程1
      • 4.2、结构体成员的访问例程2 ----- 结构体传值/传址调用
    • 5、函数调用时的参数压栈
      • 5.1、结构体参数压栈例程1
      • 2.2、参数压栈解释说明
    • 6、函数栈帧的创建与销毁

C语言结构体初阶

前言
为什么会有结构体呢?
首先,当前学习过的类型都属于内置类型(char、int、double…),单独使用
而我们想描述一个人时,一个单独的类型无法描述出来
这时就需要特殊的类型,来描述一些复杂类型 ---- struct结构体类型
如:描述一个学生
学生类型 ----> 学生变量 —>描述学生相关属性
/知识点汇总/

1、结构的基础与概念

a、结构是一些值的集合,这些值称为成员变量
b、结构的每个成员可以是不同类型的变量
c、结构体成员可以是变量,数组,指针,甚至是其他结构体
d、结构体成员中可以有另外一个结构体

结构体的声明格式

struct tag//结构体变量名
{
	member - list;//成员变量列表
}variable-list;//变量列表

1.1、结构体基础例程1 — 描述一个学生属性

/*例程1.1*/
#include <stdio.h>
//写法一:
struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
}s3,s4;//是结构体类型的变量,但属于全局变量

//写法二:
typedef struct Stu
{
	char name[20];
	int age;
	char sex[5];
	char tele[12];
}Stu;//在借助typedef的情况下,这里的Stu就属于重命名产生的新类型

int main()
{
	struct Stu s1;
	struct Stu s2;
	//s1,s2是结构体类型的变量,但属于局部变量

	Stu s5;//写法二。就可直接使用了
	return 0;
}

2、结构体成员的类型

结构体成员的类型可以是变量、数组、指针、甚至是其他结构体等多组类型成员。

2.1、结构体类型例程1 — 描述一个学生属性

#include <stdio.h>
struct B
{
	char sb;
	char arr[200];
};
struct s
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B s;
	struct B time;
};

int main()
{

	return 0;
}

3、结构体的变量定义与初识化

结构体初识化与数组类似,使用大括号

3.1、结构体的变量定义与初识化例程1

#include <stdio.h>

struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
}s1;//s1全局变量
struct S s2;//s2全局变量

int main()
{
	struct S s3;//s3局部变量
	return 0;
}

3.2、结构体的变量定义与初识化例程2

#include <stdio.h>

struct B
{
	char a;
	int i;
};

struct S
{
	char c;
	int num;
	int arr[10];
	double* pd;
	struct B ch;
	struct B* pb;
}s1;//s1全局变量
struct S s2;//s2全局变量

int main()
{
	double d = 3.14159;
	//按照顺序初识化
	struct S s3 = { 'Q',100,{1,2,3},&d,{'B',99},NULL};//s3局部变量
	//指定成员初始化: ' . ' 操作符
	struct S s4 = { .num = 999, .arr = {1,2,3,4,5} };
	//未初始化的成员,默认给NULL(0)
	return 0;
}

4、结构体成员的访问

.(点操作符 ) -> (箭头操作符)
结构体变量 . 成员
结构体指针 -> 成员
注意:一个操作数是变量。一个是指针
结构体变量的成员是通过点操作符( . )访问的,点操作符接收两个操作数

4.1、结构体成员的访问例程1

/*例程1.3*/
#include <stdio.h>
struct B
{
	char c;
	short s;
	double d;
	char* f;//指针类型成员·
};
struct stu
{
	struct B abc;
	char name[20];
	int age;
	char id[20];
}s1, s2;

int main()
{
	//结构体初始化
	struct stu s = { {'w',20,3.14159,'F'},"小强",18,"2020D2780106" };//对象
	//. ->
	//printf("%c\n",s.abc.c);
	//printf("%c\n", s.abc.f);

	struct stu* ps = &s;//结构体指针变量
	printf("%c\n",(*ps).abc.c);//*解引用+ .成员运算符,获取对应的结构体成员
	printf("%c\n", ps->abc.c);//->根据对象的指针,直接访问成员,即取结构体内成员
	return 0;
}

4.2、结构体成员的访问例程2 ----- 结构体传值/传址调用

传值调用

#include <stdio.h>
#include <string.h>
struct S
{
	char name[20];
	int age;
};
void set_s(struct S t)
{
	t.age = 18;
	//t.name = "zhangsan";//err,因为name是数组名,数组名是常量的地址
	strcpy(t.name,"zhangsan");//字符串拷贝
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(s);//传值调用,不会改变值的数据

	//写一个函数打印s中的数据
	//print_s(s);
	return 0;
}

传址调用

#include <stdio.h>
#include <string.h>
struct S
{
	char name[20];
	int age;
};
//写法一:点操作符
//void set_s(struct S* ps)
//{
//	(*ps).age = 18;
//	
//	strcpy((*ps).name, "zhangsan");//字符串拷贝
//}
//写法二: -> 操作符
void set_s(struct S* ps)
{
	ps->age = 18;
	strcpy(ps->name, "zhangsan");//字符串拷贝
}
void print_s(struct S t)
{
	printf("%s %d\n",t.name,t.age);
}
int main()
{
	struct S s = { 0 };
	//写一个函数给s中存放数据
	set_s(&s);//传址调用

	//写一个函数打印s中的数据
	print_s(s);

	return 0;
}

小结
结构体传参的考虑:
根据实际需求考虑传址或传值作为参数
传址调用性能更强:
a、传值/传址调用,传址更具优势:节约内存的空间,且速率更快
b、函数在传参时,参数是需要压栈的,如果传递一个结构体对象的时候,结构体过大,参数压栈的系统开销比较大,所以会导致性能的下降。
即:结构体传参时,常传结构体的地址

5、函数调用时的参数压栈

—是一种数据结构
压栈/出栈
理解为,盒子自上向下装,直到装满压紧,取出是却是后进先出,自上往下取出
参数压栈
每一个函数的调用都会在内存的栈区上开辟一块区域(栈区、堆区、静态区)
特点:先进后出,后进的先出

5.1、结构体参数压栈例程1

#include <stdio.h>
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;
}

2.2、参数压栈解释说明

理解:每一个函数的调用都会在总的内存的栈区上开辟一块区域,然后会暂时存储变量的内存,然后每次调用一次函数也会开辟一块内存区域,像叠盘子一样,越跌越高,形成了堆叠,也就是压栈。直到函数执行完,里面的局部变量使出作用域,相继内存也得以释放,就像把刚堆叠的盘子再从上向下,拿取出去,也就是释放了空间。
如图所示
在这里插入图片描述

总结就是:先进后出,后进先出

6、函数栈帧的创建与销毁

可参考这位博主,写得很好:
链接: 函数栈帧的创建与销毁

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

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

相关文章

C++多线程场景中的变量提前释放导致栈内存异常

多线程场景中的栈内存异常 在子线程中尝试使用当前函数的资源&#xff0c;是非常危险的&#xff0c;但是C支持这么做。因此C这么做可能会造成栈内存异常。 正常代码 #include <iostream> #include <thread> #include <windows.h>// 线程函数&#xff0c;用…

截止到目前全量主体总数有多少?

企业主体类型 企业主体类型有很多种&#xff0c;一般我们会分为公司&#xff08;有限责任&#xff09;、合伙企业、个人独资企业、个体经营户这些类别。 今天我们按照企业&#xff0c;个体&#xff0c;组织的分类方式来看各个主体的总数。 企业&#xff1a;统一社会信用代码…

三、性能测试场景设计

性能测试场景设计 一、引言&#xff1a;如果公司要求你去做性能测试&#xff0c;遇到这些场景&#xff0c;我们要如何设计&#xff1f;二、6种常见设计方法1、普通性能场景设计2、负载测试性能场景 一、引言&#xff1a;如果公司要求你去做性能测试&#xff0c;遇到这些场景&am…

读高性能MySQL(第4版)笔记01_MySQL架构(上)

1. 逻辑架构 1.1. 大多数基于网络的客户端/服务器工具或服务器都有类似的服务 1.1.1. 连接处理 1.1.2. 身份验证 1.1.3. 确保安全性 1.2. 核心层 1.2.1. 查询解析、分析、优化、以及所有的内置函数 1.2.2. 跨存储引擎的功能 1.2.2.1. 存储过程 1.2.2.2. 触发器 1.2.2…

kafka的位移

文章目录 概要消费位移__consumer_offsets主题位移提交 概要 本文主要总结kafka的位移是如何管理的&#xff0c;在broker端如何通过命令行查看到位移信息&#xff0c;并从代码层面总结了位移的提交方式。 消费位移 对于 Kafka 中的分区而言&#xff0c;它的每条消息都有唯一…

Python爬虫(十二)_XPath与lxml类库

Python学习指南 有同学说&#xff0c;我正则用的不好&#xff0c;处理HTML文档很累&#xff0c;有没有其他的方法&#xff1f; 有&#xff01;那就是XPath,我们可以用先将HTML文档转换成XML文档&#xff0c;然后用XPath查找HTML节点或元素。 什么是XML XML指可扩展标记语言(E…

Spring Boot + Vue3前后端分离实战wiki知识库系统十二--用户管理单点登录开发一...

目标&#xff1a; 在上一次https://www.cnblogs.com/webor2006/p/17533745.html我们已经完成了文档管理的功能模块开发&#xff0c;接下来则开启新模块的学习---用户登录&#xff0c;这块还是有不少知识点值得学习的&#xff0c;先来看一下整体的效果&#xff0c;关于效果官网有…

算法|Day38 动态规划6

完全背包问题&#xff0c;也就是一个物品可以取多次&#xff0c;我们只需要正序遍历背包容量就可以了。因为一维数组是按左边的状态来进行推导&#xff0c;我们正序&#xff0c;那样就会将前一次取的状态带到下一个位置&#xff0c;也就实现了多次取。如果倒序&#xff0c;左边…

麦肯锡发布《2023科技趋势展望报告》,生成式AI、下一代软件开发成为趋势,软件测试如何贴合趋势?

近日&#xff0c;麦肯锡公司发布了《2023科技趋势展望报告》。报告列出了15个趋势&#xff0c;并把他们分为5大类&#xff0c;人工智能革命、构建数字未来、计算和连接的前沿、尖端工程技术和可持续发展。 类别一&#xff1a;人工智能革命 生成式AI 生成型人工智能标志着人工智…

(el-Table)操作(不使用 ts):Element-plus 中Table 表格组件:多选修改成支持单选及表格相关样式的调整

Ⅰ、Element-plus 提供的 Table 表格组件与想要目标情况的对比&#xff1a; 1、Element-plus 提供 Table 组件情况&#xff1a; 其一、Element-ui 自提供的 Table 代码情况为(示例的代码)&#xff1a; // Element-plus 自提供的代码&#xff1a; // 此时是使用了 ts 语言环境…

Windows11中使用OneDrive按Print Screen截屏按键,把截图自动保存到OneDrive中

参考&#xff1a;关于Onedrive 我已经勾选了自动保存屏幕截图 但是我截图之后我的图片并没有上传到onedrive上面 - Microsoft Community 1. 打开Windows 11的设置&#xff0c;可以通过按下Win I键来快速打开设置&#xff1b; 2. 设置--辅助功能--键盘--使用”print Screen“键…

Rust 重载运算符|复数结构的“加减乘除”四则运算

复数 基本概念 复数定义 由实数部分和虚数部分所组成的数&#xff0c;形如a&#xff0b;bi 。 其中a、b为实数&#xff0c;i 为“虚数单位”&#xff0c;i -1&#xff0c;即虚数单位的平方等于-1。 a、b分别叫做复数a&#xff0b;bi的实部和虚部。 当b0时&#xff0c;a&…

codeforces代:

感受思维的美丽&#xff0c;abcde题目的思路是怎么样的&#xff1a; 上蓝 上紫 可以代 &#xff1a;有问题可以评论区 直接问我 也可以q: 639682754

【严重】Smartbi未授权设置Token回调地址获取管理员权限

漏洞描述 Smartbi是一款商业智能应用&#xff0c;提供了数据集成、分析、可视化等功能&#xff0c;帮助用户理解和使用他们的数据进行决策。 在 Smartbi 受影响版本中存在Token回调地址漏洞&#xff0c;未授权的攻击者可以通过向目标系统发送POST请求/smartbix/api/monitor/s…

python_PyQt5运行股票研究python方法工具V1.0

写在前面&#xff1a; 1 在写研究方法过程中&#xff08;例如&#xff1a;股票研究&#xff09;&#xff0c;很多方法根据数据的更新需要重复运行获取新的结果&#xff0c;本工具就是固化这些需要重复运行的代码&#xff0c;可以直接在工具中运行得到更新的结果。 2 本文是V1…

并发编程系列-Semaphore

Semaphore&#xff0c;如今通常被翻译为"信号量"&#xff0c;过去也曾被翻译为"信号灯"&#xff0c;因为类似于现实生活中的红绿灯&#xff0c;车辆是否能通行取决于是否是绿灯。同样&#xff0c;在编程世界中&#xff0c;线程是否能执行取决于信号量是否允…

DevOps?自动化运维!

by: 雪月三十 DevOps流程图 DevOps介绍 命名 DevOps是Dev和Ops的结合 Dev&#xff08;developer开发&#xff09; Ops&#xff08;operation运维&#xff09; 矛盾 在企业中dev和ops是有一种天然的矛盾&#xff0c;dev要求的是快速迭代&#xff0c;给公司挖掘出商业的价值…

c++实现多进程执行多个shell脚本

一 参考 system()、exec()、fork()三个与进程有关的函数的比较 - 青儿哥哥 - 博客园 (cnblogs.com)https://www.cnblogs.com/qingergege/p/6601807.htmlfork执行流程分析_fork子进程和父进程执行顺序_cytf的博客-CSDN博客https://blog.csdn.net/qq_27420299/articl

IE实验-Qos教学实验

S1 diffserv domain boss //创建差分服务域 8021p-inbound 0 phb ef green //将外部优先级为0的流量&#xff0c;映射到内部优先级ef interface GigabitEthernet0/0/2 trust upstream boss //在接口下调用查分服务域 trust dscp override qos map-table dscp-dscp acl …

【新品发布】ChatWork企业知识库系统源码

系统简介 基于前后端分离架构以及Vue3、uni-app、ThinkPHP6.x、PostgreSQL、pgvector技术栈开发&#xff0c;包含PC端、H5端。 ChatWork支持问答式和文档式知识库&#xff0c;能够导入txt、doc、docx、pdf、md等多种格式文档。 导入数据完成向量化训练后&#xff0c;用户提问…