结构体联合体和枚举吧

本文详细介绍了C/C++中的结构体创建、内存对齐规则、位段和联合体的概念,强调了在定义结构体时需考虑内存效率,并展示了如何通过联合体测试大小端问题。
摘要由CSDN通过智能技术生成

结构体的创建


需要使用关键字  struct,加上创建类型的类型名 比如s1  然后定义结构体的成员,至少有一个,之后就可以使用结构体类型  struct s1来创建变量了
,如struct s1 stu。
而结构体的传参有两种方式,第一种就是形参,不改变结构体的内容,比如打印结构体成员的值,只要结构体名.结构体成员即可访问。
而另一个则是实参,将结构体的地址传入,以上面创建的结构体为例,只需要加上一个 * 号即可,struct s1*    此时只需要结构体名->结构体成员就可以打印出来。这两个看起来好像并没什么差别,但是如果是形参要打印一千一万个内容,它会真的去创建出来,对内存是很浪费的,但是实参不同,它并不会真的创建,它从头到尾只有一个地址的大小,说到这里用谁懂得都懂了吧。

内存对齐


结构体还有一个计算上的点,那就是内存对齐
每个编译器都有一个默认的值,这个值和它类型本身的大小,如int  4个字节,取小的那个,那么从0开始存,它将会在刚好是他倍数的位置开始存入。

如图所示结构体


结构体成员有三个,第一个是char,第二个是int,第三个成员也是char,那么如果我们去计算结构体大小将会是12,如图所示。

因为char虽然只占了一个字节,但是第二个int由于内存对齐原则char存在了0的位置,并且由于1,2,3并不能整除它,所以他将会从4的位置开始存,而后面的char虽然也只占了一个字节,但是总长度需要是最大成员的倍数,所以还需要浪费三个空间,最后计算出来的长度是12,但是如果我们的结构体是char char int 那么就可以少浪费空间,让它的长度变成8,如图所示。

所以我们在定义结构体的时候,也是需要考虑一下顺序的。


结构体内有结构体的情况
那如果结构体里面有结构体又该怎么计算呢,它只算结构体最大的成员的大小,如图所示的结构体


此时,被包含的结构体只取最大的那个,这样char占一个,被包含结构体的最大成员是4,

跳过三个内存开始存入,上面已经计算出s1的大小是8,所以存八个字节,short紧随其后占

两个位置,目前已经占了14个字节的位置,和默认对齐数4并不是倍数,所以又要对齐,最后得出大小是16

位段


还有一个只能在结构体内部创建的东西叫位段
同样需要用struct定义  变量的创建格式也差不多,正常是int a  那么位段则是int _a :2
下划线是为了方便让我们识别出他是位段,可以不写,而冒号不能省略,冒号后面的数字代表给他分配多少个比特位的大小。
而位段是怎么存入数据的呢
如图所示,我们先定义一下内容,再存入一下数据。


它在内部是一次性开辟完所有空间的,但是为了方便讲解,我们一个一个开,首先先开辟一个char类型的空间8个比特位,这时候产生一个问题,从右开始存还是从左开始存呢,根据编译器的不同定义也不同,vs里是从右开始的。

它的转换是先转换成二进制 a是00001000     b是00001010  c是00000101

但是我们只给a分配了3个比特位存不完怎么办,会发生截断,只取最右边的三个,存在第一个开辟空间的最右边,而b可以存入五个,那么第一个字节的内容就是01010000。

到c了,但是没用位置了,所以我们再开辟八个比特位给他 存入0000101,同样是存右边,而他的左边第一位由于我们初始化了所以是0,第二个字节的内容就是00000101,右边七个是保存过来的,左边第一个是初始化定义的。我们来验证一下是不是这么存在内存里的,首先要先转成16进制

0101 0000  0000 0101

5         0          0          5

内存如图所示

正如我们所料。

如果这时候我们发现内存不够用了,但是又没有用完,在vs里是直接丢弃不用,在别的编译器情况则可能不同。不够用的情况下我们会再开辟一个char类型的空间出来,数据存完但是空间没有用完,剩下的空间也不再使用了。而在位段内,也是需要履行内存对齐原则的,所以他最后的值是2。

如图所示


如果没有内存对齐原则那么在别的编译器内需要去记录之前编译器一次访问多少字节,再根据自己的规则进行调整,这样太麻烦了,索性牺牲一点空间,来减少计算的次数。而位段,它在不同编译器下,由于环境不同,无法确定具体的值,从而导致它并不支持跨平台,但是如果你硬要跨也可以,你需要每跨一次平台,根据它平台的规则重新定义你位段的大小。

联合体

联合体又被称为共用体,因为不论它有多少个成员,但是它始终只会开辟并使用其中最大成员的大小。如图所示确实如我说的

而由于是使用同一块空间,所以会出现明明赋值给的啊,但是b也被赋值的效果

这时候可以把他运用到测试大小端的问题上,在学联合体之前可能要敲一堆代码测,现在联合体几行就能搞定,如图所示

这样就能看出大小端存放。

枚举

枚举就像数组一样,是相同类型的集合,而里面的数据也像数组一样从0开始,需要注意的是,如果我们篡改了其中一个的值,那么它之后的值也会被改变,如图所示

当我们篡改某个值为255之后,他后面的数并没有继续打印3,而是按255+1来算,而正是由于这种特性,之前我们使用switch的时候或许里面的case1234并不好识别到底是干什么的,我们就可以利用枚举类型来给他取一个更好辨认的值出来。

  • 17
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值