从浅入深掌握进阶结构体(C语言)

2023-12-09 00:01

本文主要是介绍从浅入深掌握进阶结构体(C语言),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言
这一期我们将继续讲解结构体的知识,还没有看过上一期的小伙伴一定要赶紧去学习哦。
上一期,冲鸭!
那么话不多说我们开始今天的学习吧!
在这里插入图片描述

文章目录

  • 1,结构体的自引用
  • 2,匿名结构体
  • 3,位段
  • 4,结构体的传参
  • 5,尾声

1,结构体的自引用

什么是结构体的自引用呢?简单来说就是自己装自己(有点类似递归)。
那么是这样自引用的么?

struct student
{
char name[20];
int age;
float score;
struct student next_student;//这是我们自己定义的一个类型的解耦提变量如果可以这样写,我们就可以在一个学生的结构体里包含下一个学生的结构体,如果有一百个学生,我们就可以通过第一个学生访问到第一百个学生
}stu1;

但是这样写好像有问题啊,我们刚学过内存对齐的知识,在编译期间,编译器需要知道结构体变量大小为结构体变量分配空间,可是这个好像没法知道这个结构体变量的大小是多少,会陷入无限的递归之中。那我们是不是可以换个思路呢?我们不是在结构体成员中加入下一个学生的结构体变量,而是加入下一个学生的结构体变量的地址不就可以了么,这样就不会陷入无限的递归之中。而且我们能通过地址寻找到下一个学生的信息。书写方式如下:

struct student
{
char name[20];
int age;
float score;
struct student* next_student;//储存下一个学生(结构体变量)的地址
}stu1;

2,匿名结构体

匿名结构体是什么呢?就拿我们刚才创建了类型为为student的结构体。如果我们这样写代码呢?

struct 
{
char name[20];
int age;
float score;
}stu1;

是不是发现少了student,这种特殊的声明我们就称之为匿名结构体。
但是需注意的是匿名结构体的变量只能在声明时创建且只能有一个变量。也就是说只能使用一次,我们不能对匿名结构体自引用。

3,位段

学习位段之前我们先看如下代码。

struct student
{
char name[20];
int age:6;
int score:8;
}

我们发现该结构体的成员中年龄和分数后面多了一个:和一个数字,这是代表什么意思呢?正常情况下,一个学生的年龄应该在6-31岁之间,因为年龄是个整形数据,所以会给它分配4个字节大小的空间,但是如果只要表达0-31这些数字的话完全不需要那么大的空间对于有符号整形来说只需要6个bit位就足够了,那么回到代码,int age:6;的意思就是给这个整形分配6个比特的空间。而score给他分配了8个字节的空间。那么这个时结构体的内存是如何分配的呢?

struct uma
{
int a:2;
int b:3;
int c:5;
int d:10;

以这个结构体为例。
在这里插入图片描述
相比通过这张图片就能够了解位段是如何分配空间的了。
但是我们还需注意以下几点。
1, 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以 选择其他类型。
2, 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。

4,结构体的传参

在函数中我们该怎么对结构体进行传参呢?
我们有以下两种方法

#include <stdio.h>
struct Student
{int data[1000];int num;
};
struct Student s = { {1,2,3,4}, 1000 };
//结构体传参
void print1(struct Student s)
{printf("%d\n", s.num);
}
//结构体地址传参
void print2(struct Student* ps)
{printf("%d\n", ps->num);
}
int main()
{print1(s); //传结构体print2(&s); //传结构体的地址return 0;
}

那么这两种写法哪种更好呢?没错就是第二种,因为直接传递结构体的话,计算机会给形参重新开辟一块内存空间,小的还好说,要是特别大的结构体那么会相当的浪费内存,而传递地址就不一样了并不需要重新开辟一片空间,可以提升程序的性能。

5,尾声

学习完这两篇博客的小伙伴想必已经非常了解了结构体的用法,但是也要多加练习哦正所谓熟能生巧,下次我将找几道结构体的题目来跟大家分享一下。结构体习题链接,gogogo!
如果觉得博主讲的不错的千万不要忘记关注博主哦,你们的关注我是最大的动力!

这篇关于从浅入深掌握进阶结构体(C语言)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/471775

相关文章

C语言中位操作的实际应用举例

《C语言中位操作的实际应用举例》:本文主要介绍C语言中位操作的实际应用,总结了位操作的使用场景,并指出了需要注意的问题,如可读性、平台依赖性和溢出风险,文中通过代码介绍的非常详细,需要的朋友可以参... 目录1. 嵌入式系统与硬件寄存器操作2. 网络协议解析3. 图像处理与颜色编码4. 高效处理布尔标志集合

Go语言开发实现查询IP信息的MCP服务器

《Go语言开发实现查询IP信息的MCP服务器》随着MCP的快速普及和广泛应用,MCP服务器也层出不穷,本文将详细介绍如何在Go语言中使用go-mcp库来开发一个查询IP信息的MCP... 目录前言mcp-ip-geo 服务器目录结构说明查询 IP 信息功能实现工具实现工具管理查询单个 IP 信息工具的实现服

C 语言中enum枚举的定义和使用小结

《C语言中enum枚举的定义和使用小结》在C语言里,enum(枚举)是一种用户自定义的数据类型,它能够让你创建一组具名的整数常量,下面我会从定义、使用、特性等方面详细介绍enum,感兴趣的朋友一起看... 目录1、引言2、基本定义3、定义枚举变量4、自定义枚举常量的值5、枚举与switch语句结合使用6、枚

Go 语言中的select语句详解及工作原理

《Go语言中的select语句详解及工作原理》在Go语言中,select语句是用于处理多个通道(channel)操作的一种控制结构,它类似于switch语句,本文给大家介绍Go语言中的select语... 目录Go 语言中的 select 是做什么的基本功能语法工作原理示例示例 1:监听多个通道示例 2:带

C语言函数递归实际应用举例详解

《C语言函数递归实际应用举例详解》程序调用自身的编程技巧称为递归,递归做为一种算法在程序设计语言中广泛应用,:本文主要介绍C语言函数递归实际应用举例的相关资料,文中通过代码介绍的非常详细,需要的朋... 目录前言一、递归的概念与思想二、递归的限制条件 三、递归的实际应用举例(一)求 n 的阶乘(二)顺序打印

Spring Boot + MyBatis Plus 高效开发实战从入门到进阶优化(推荐)

《SpringBoot+MyBatisPlus高效开发实战从入门到进阶优化(推荐)》本文将详细介绍SpringBoot+MyBatisPlus的完整开发流程,并深入剖析分页查询、批量操作、动... 目录Spring Boot + MyBATis Plus 高效开发实战:从入门到进阶优化1. MyBatis

使用Java实现通用树形结构构建工具类

《使用Java实现通用树形结构构建工具类》这篇文章主要为大家详细介绍了如何使用Java实现通用树形结构构建工具类,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 目录完整代码一、设计思想与核心功能二、核心实现原理1. 数据结构准备阶段2. 循环依赖检测算法3. 树形结构构建4. 搜索子

利用Python开发Markdown表格结构转换为Excel工具

《利用Python开发Markdown表格结构转换为Excel工具》在数据管理和文档编写过程中,我们经常使用Markdown来记录表格数据,但它没有Excel使用方便,所以本文将使用Python编写一... 目录1.完整代码2. 项目概述3. 代码解析3.1 依赖库3.2 GUI 设计3.3 解析 Mark

C语言中的数据类型强制转换

《C语言中的数据类型强制转换》:本文主要介绍C语言中的数据类型强制转换方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录C语言数据类型强制转换自动转换强制转换类型总结C语言数据类型强制转换强制类型转换:是通过类型转换运算来实现的,主要的数据类型转换分为自动转换

利用Go语言开发文件操作工具轻松处理所有文件

《利用Go语言开发文件操作工具轻松处理所有文件》在后端开发中,文件操作是一个非常常见但又容易出错的场景,本文小编要向大家介绍一个强大的Go语言文件操作工具库,它能帮你轻松处理各种文件操作场景... 目录为什么需要这个工具?核心功能详解1. 文件/目录存javascript在性检查2. 批量创建目录3. 文件