结构体的初步介绍

本文介绍了C语言中结构体的概念,包括其用途、初始化方式(按顺序和不按顺序)、特殊声明(匿名结构体),以及内存对齐的重要性,解释了对齐规则并以实例说明。还讨论了位段的应用,展示了如何利用位段进行空间管理和访问结构体成员的技巧。
摘要由CSDN通过智能技术生成

在学习数学的时候,我们知道有一个操作叫做“合并同类项”,有助于简化自己的计算操作。

而在C语言里,我们尝尝苦于写变量名,比如str1,str2。谁记得住这些数组里,到底哪个是我需要的那个?

这个时候,结构体就出现了,犹如救世主一样。

一、结构体是什么?

如图是一个结构体的演示。

其中,struct为结构体关键词,Stu为结构体类型,里面的name、grade、age是该结构体的成员变量(本质上仍是变量)

二、结构体的初始化

结构体的初始化可以有多种形式。

(1)按顺序初始化

(2)不按顺序初始化

随意的赋值,但是第一行按顺序初始化,第二行则不按顺序初始化。

第二种比较自由(而且VS这种有提示词的,可以帮助看一下哪个变量还没有赋值)缺点是赋值的时候有点累,需要先指向成员变量再赋值。

第一种按照顺序赋值即可,缺点是成员变量多时,可能记不住顺序。

三、结构体的特殊声明

我们在结构体声明时,可以不完全声明。

我们称之为匿名结构体。

但是这种结构体不重命名的情况下,难以二次使用,所以不建议使用匿名结构体。

四、结构内存对齐

有没有好奇宝宝想试试看sizeof(结构体)的呢?

这个时候会发现,有些情况下符合我们的认知,有些则不能。

比如以下两个式子。

明明这个时候两个结构体存储的东西都一样,为什么内存大小不一样呢?

而且,按照原先我们的认知,Stu和Stu1难道不应该都是10个字节的大小吗?为什么变成了12个字节呢?(4+4+1+1=10)

这个时候,结构体的内存对齐就闪亮登场了!

(1)什么是内存对齐?

首先得掌握结构体的对齐规则:
1. 结构体的第⼀个成员对齐到和结构体变量起始位置偏移量为0的地址处
2. 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处。
对齐数 = 编译器默认的⼀个对齐数 与 该成员变量大小的较小值。
3. 结构体总大小为最大对齐数(结构体中每个成员变量都有⼀个对齐数,所有对齐数中最大的)的
整数倍。
4. 如果嵌套了结构体的情况,嵌套的结构体成员对齐到自己的成员中最大对齐数的整数倍处,结构
体的整体大小就是所有最大对齐数(含嵌套结构体中成员的对齐数)的整数倍。
很抽象,现在用人话说一下。
先讲对齐数。
在VS里,默认对齐数一般为8,而Linux的gcc里则默认为成员变量自己的大小。
每个成员变量的对齐数需取该变量大小和默认对齐数两者之间的小值。
比如int类型的对齐数就是4(因为4<8)
以这个Stu为例分析
name是一个字节,并且放在偏移量为0的位置。
然后是grade,是4个字节。
grade的位置需要满足:地址是它的对齐数的整数倍。

grade是int类型,所以对齐数为4。所以grade不能放在偏移量为1的地方(即name之后)而是放在偏移量为4的地方。

而后的name2,类型为char,对齐数为1,直接放在后面即可。

再后的age,类型为int,对齐数为4,所以应该放在偏移量为12的地方(4+4+4)。

也就得到了16的结果(4+4+4+4)

同时做个小练习,这个结构体的大小为什么是12?

(2)为什么存在对齐?

大部分参考资料是:

1、部分设备存在硬件问题,某些硬件平台只能在某些地址取某些特定类型的数据,否则则会硬件异常。

2、数据结构应尽可能在自然边界上对齐。当读取到double类型时,处理器总是从内存里提取8个字节。如果double类型没有被对齐,那么处理就至少需要两次内存访问才可以得到这个double的内容。

所以,实际上对齐的行为是以空间换时间的行为。

所以像上面两个例子,我们应该将比较小的部分全都放在一起,减少浪费的空间。

(3)对于结构体内存有什么解决方法?

答:有,甚至能进一步缩小结构体所占内存。但是功能越强,安全性的问题也会凸显。

此物名曰——位段

位段

位段的声明和结构是类似的,有两个不同:

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

(还是Stu)

如图便是位段的使用。

需要注意的是,冒号后方的数字,是该成员变量占用的bit位个数

我们知道1byte=8bit。而我们以前认为的最小的空间是char的1byte。

所以学会了位段,可以称为空间管理大师了。

需要注意的是,由于1个字节1个地址,所以我们不能直接scanf访问改变其中的变量。

而是通过先给一个变量scanf,然后再访问结构体为成员变量赋值。

  • 28
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值