自定义类型:结构体

前言

hello呀!各位博友,今天,我们来一起探讨一下有关结构体的知识内容,从浅到深,对于想了解某个具体点的同学可以直接点击目录查看,不了解此版块的内容的博友可以依次往下看。接下来我们废话不都说,直接开始吧!

一、什么是结构体

在C语言中,我们有着许许多多的内置类型,但是我们试想一下,单一的类型是否足够描述生活中的所有事物呢?很显然,那是不够的,比如我们要描述一本书的时候,要描述书的类型,书的名字,书的页码,所以呢,就诞生结构体这个自定义数据类型了。

二、结构体的基础内容

1.结构体的关键字struct

在这里插入图片描述
我们想要创建一个结构体时,那么就一定要清楚结构体的关键字struct,就如上图所示,我们在关键字的后边给自己创建的结构体起上名字,在大括号中间是结构体的成员列表,在最后一个大括号后边是变量名列表,举个例子,如果我们想要描述一本书,那么就先创建一个书的结构体,就在结构体关键字后边加上名字,就以book为例子,那么我们就要对书的名字,书的页码,书的作者等一系列进行叙述,那么我们所说的这些就是书的构成成员,就将这些描述在大括号内,那么我们描述的书肯定不止一本,那么我们就可以在变量名列表上添加我们需要描述的书,以下图为例,大家可以理解一下在这里插入图片描述

2.结构体变量的初始化

当我们创建好结构体变量以后,那么就要对其数值进行初始化,我们按照大括号内的变量名称顺序进行赋值,例如下图所示在这里插入图片描述
这样,我们就给其结构体的变量进行了赋值

3.结构体成员访问操作符

当我们想要访问结构体的成员内容的时候,以(.)的方式来直接访问,比如我想要打印一下上图的结构体内容,就可以如图所示在这里插入图片描述
当我们在创建的b1后面打上(.)时,就会发现出现了我们创建的结构体变量名称,让我们来完整看看,访问后打印的效果在这里插入图片描述
这便是直接访问,总结来说,使用方式:结构体变量.变量成员名。当然了,既然有直接访问,那也就有间接访问,有些时候,我们得到的不是一个结构体变量,而是得到了一个指向结构体的指针,此时我们想要访问结构体就需要使用(->)来进行访问,具体看下图展示在这里插入图片描述

总结来说,其使用方法就是:结构体指针(->)成员名

4.结构的特殊声明

在声明结构体的时候,可以不完全声明,也就是匿名结构体,我们要注意,匿名结构体只能使用一次!在这里插入图片描述

5.结构体的自引用

在结构中包含⼀个类型为该结构本⾝的成员是否可以呢?
⽐如,定义⼀个链表的节点在这里插入图片描述
上述代码正确吗?如果正确,那 sizeof(struct Node) 是多少?仔细分析,其实是不⾏的,因为⼀个结构体中再包含⼀个同类型的结构体变量,这样结构体变量的⼤,⼩就会⽆穷的⼤,是不合理的。
正确的⾃引⽤⽅式:在这里插入图片描述

三、结构体的内存对齐

接下来我们来试想一个问题,在结构体里面,有着不同的数据类型,那么结构体的内存大小该如何计算呢?从考点的角度来说,也就是我们所说的结构体内存对齐。

1.对齐规则

我们要了解结构体的内存对齐,那么我们首先就得知道对齐规则。
规则:

  1. 结构体的第⼀个成员对⻬到和结构体变量起始位置偏移量为0的地址处
  2. 其他成员变量要对⻬到某个数字(对⻬数)的整数倍的地址处。
    对⻬数 = 编译器默认的⼀个对⻬数 与 该成员变量⼤⼩的较⼩值。
  • VS 中默认的值为 8
  • Linux中 gcc 没有默认对⻬数,对⻬数就是成员⾃⾝的⼤⼩
  1. 结构体总⼤⼩为最⼤对⻬数(结构体中每个成员变量都有⼀个对⻬数,所有对⻬数中最⼤的)的
    整数倍。
  2. 如果嵌套了结构体的情况,嵌套的结构体成员对⻬到⾃⼰的成员中最⼤对⻬数的整数倍处,结构
    体的整体⼤⼩就是所有最⼤对⻬数(含嵌套结构体中成员的对⻬数)的整数倍。

光看是不易理解的,我们来看下图所示:在这里插入图片描述
通过上述图片,我相信大家应该可以理解了结构体内存对齐,那么我们将此代码跑起来观察一下,其是否大小真如我们所按照规则算出来的8呢在这里插入图片描述
我们可以看到,结果真的是8,所以希望大家在计算结构体大小时,一定要牢记我们的规则!

2.为什么会存在内存对齐

其实对于这个问题,我们只需要了解即可,总的来说呢就2个原因,一个是平台原因,一个是性能原因,这俩个原因总体来说可以总结出一个结论:结构体的内存对齐是拿空间来换取时间的做法。大家只需知道这个即可。

我们知道了结构体的内存对齐规则以后就不难明白,我们在设计结构体时,如果想要节省空间,那么我们就要尽量将内存小的放在一起。

3.修改默认对齐数

其实对于编译器的默认对齐数我们是可以进行修改的,需要用到指令#pragma,具体操作请看下图在这里插入图片描述
这样我们就可以修改自己所想要的对齐数,不过值得注意的是,我们在设计的时候,一般都是偶数,例如1,2,4等
因为大部分的内存都为偶数

四、结构体传参

我们都知道传参的时候分为传值与传址,那么我们的结构体也存在,大家请看下图在这里插入图片描述
上⾯的 print1 和 print2 函数哪个好些?
答案是:⾸选print2函数。
原因:函数传参的时候,参数是需要压栈,会有时间和空间上的系统开销。
如果传递⼀个结构体对象的时候,结构体过⼤,参数压栈的的系统开销⽐较⼤,所以会导致性能的下降。
结论:
结构体传参的时候,要传结构体的地址。

五、结构体实现位段

结构体的内容就大差不差啦,我们接着来看看结构体实现位段

1.什么是位段

那么到底什么是位段呢?我们来看看这段话
位段的声明和结构是类似的,有两个不同:

  1. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以
    选择其他类型。
  2. 位段的成员名后边有⼀个冒号和⼀个数字。

光看啊可能不太能够理解,我们来看看示例图在这里插入图片描述
这就是一个位段,那么既然它是基于结构体,那么位段A的大小又是多少呢?

2.位段的内存分配

  1. 位段的成员可以是 int unsigned int signed int 或者是 char 等类型
  2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的⽅式来开辟的。
  3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。

对于位段的内存开辟,重点记住第二条,每次以4或1个字节进行开辟的,不用过多了解

3.位段的跨平台问题

大家可以参考一下下面的文献:

  1. int 位段被当成有符号数还是⽆符号数是不确定的。
  2. 位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会
    出问题。
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。
  4. 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃
    剩余的位还是利⽤,这是不确定的。

总结:
跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

4.位段的运用

对于位段的运用,大家其实也就只需了解一下即可,那就是合理使用位段,可以使得帮助网络畅通.

5.位段的注意事项

位段的⼏个成员共有同⼀个字节,这样有些成员的起始位置并不是某个字节的起始位置,那么这些位置处是没有地址的。内存中每个字节分配⼀个地址,⼀个字节内部的bit位是没有地址的。所以不能对位段的成员使⽤&操作符,这样就不能使⽤scanf直接给位段的成员输⼊值,只能是先输⼊放在⼀个变量中,然后赋值给位段的成员。
在这里插入图片描述

总结

在此篇文章呢,和各位博友一起学习了关于结构体的全部内容,什么是结构体,结构体的内存对齐,位段等内容,希望各位博友通过此篇文章可以更加的理解结构体的内容。我是编程渝小黔,为您持续带来编程知识文章,我们下期再见~~

1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。1、资源项目源码均已通过严格测试验证,保证能够正常运行; 2、项目问题、技术讨论,可以给博主私信或留言,博主看到后会第一时间与您进行沟通; 3、本项目比较适合计算机领域相关的毕业设计课题、课程作业等使用,尤其对于人工智能、计算机科学与技术等相关专业,更为适合; 4、下载使用后,可先查看README.md文件(如有),本项目仅用作交流学习参考,请切勿用于商业用途。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值