从浅入深掌握进阶结构体(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

相关文章

从基础到进阶详解Pandas时间数据处理指南

《从基础到进阶详解Pandas时间数据处理指南》Pandas构建了完整的时间数据处理生态,核心由四个基础类构成,Timestamp,DatetimeIndex,Period和Timedelta,下面我... 目录1. 时间数据类型与基础操作1.1 核心时间对象体系1.2 时间数据生成技巧2. 时间索引与数据

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

JDK9到JDK21中值得掌握的29个实用特性分享

《JDK9到JDK21中值得掌握的29个实用特性分享》Java的演进节奏从JDK9开始显著加快,每半年一个新版本的发布节奏为Java带来了大量的新特性,本文整理了29个JDK9到JDK21中值得掌握的... 目录JDK 9 模块化与API增强1. 集合工厂方法:一行代码创建不可变集合2. 私有接口方法:接口

Python+PyQt5实现文件夹结构映射工具

《Python+PyQt5实现文件夹结构映射工具》在日常工作中,我们经常需要对文件夹结构进行复制和备份,本文将带来一款基于PyQt5开发的文件夹结构映射工具,感兴趣的小伙伴可以跟随小编一起学习一下... 目录概述功能亮点展示效果软件使用步骤代码解析1. 主窗口设计(FolderCopyApp)2. 拖拽路径

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细