结构体,联合体,枚举,位段

结构体:

结构体就是一个可以存放多个类型的集合,如图

8cfd62b578d4490fa61b2d3569fbdeb3.png

结构体的对齐规则

对齐数 = 编译器默认的一个对齐数 与 该成员大小的较小值

220edc0dd8e443e38a59269a1666d682.png

结构体为什么要内存对齐?

1.平台原因

不是所有平台都可以在任意位置访问数据,有些平台只能在特定位置(比如规定int类型只能是在4的整数倍处访问,double类型只能在8的整数倍处访问)访问数据,否则会抛出硬件异常

2.性能原因

假设一个机器每次访问数据为4个字节,则访问的地址必须是4的倍数,如果没有内存对齐那么

我们对i数据进行访问时则需要访问两次才可以得到i的数据,如果内存对齐了,我们只需要访问一次就可以访问到i的数据;内存对齐实际上就是一种以空间换时间的方式。

40eac22f6ca04da29d2cbae20febb189.png

注:我们写代码的过程中可以调整类型的顺序来减少空间

ecf95fd47d264f7aa326aba215b024b2.png

大小为12

2e8937cdaf15407d914cf4203b628e66.png

大小为8

 

 

联合体:

联合体各元素采用内存共享的方式存储,当其中一个数据改变会影响其他数据。

7a24c8c598ef4368ab2759876e4240e1.png

以小端存储为例,当向i变量输入10000,此时内存上的是10 27 00  00

再向c里输入1时,内存则变为01 27 00 00

8b9b01a2dd224b2dbdaec7d05344b20f.png

80bfac26a9384ad9ab6ffce8b65862ef.png

联合体的大小的计算

1.先求出该结构体最大元素的大小,保证最大元素可以存储

2.从最大元素的大小和编译器内存对齐的规定的大小中取较小值,使得结构体大小大于最大元素的大小,且为较小值的整数倍

注意:联和体内数组的对齐数是数组所存储类型的对齐数

c7ef698848754f70bd372c038082a84f.png

那联合体有什么应用场景呢?

2a7b17e97c9f4f6dad091a14fc6dc5a4.png

如图当我们要设计一个抽奖的礼物列表,抽奖只会抽中其中一样就可以如上图设计来减少内存占用;这样设计类似于多态

 

 

枚举

枚举就是在这个结构里给一个整形常量取一个别名,也是就是之前的宏定义那样,当时书写起来比宏定义简单,放在一个结构体里更好维护 

而且将变量定义在枚举类型里面会有类型检查,如果直接给枚举变量赋值时只能给enum内的常量名,不能给数字,否则会编译报错,但是在使用scanf给枚举常量赋值时是输入对应数字的,要注意。(要测试的话要在c++下,c语言的检查并不严格)

0a74192fb2bf4a338285c3b31703cc49.png

如果没给初始值的话第一个默认为0,后面的没给值的话就是前一个+1;所以RED,GREEN,BLUE分别对应0,1,2

 

d7dd985bf28343a98949b5713c7cfb65.png

RED,GREEN,BLUE分别对应1,2,3

3827002e0be044d0ba99c0a80c1532c8.png

我们也可以自由赋值

 

位段

位段是基于结构体的一中特殊数据结构,位段只能是int或者是char类型,位段的目的是减少内存,但使用了位段也会降低效率,所以当我们内存的需求非常大时才会使用,(比如在网络中,如下图)

0466c6dae67b424294b3b164faad887c.png

位端的大小计算

1.如果相邻的数据类型相同且相加的比特位数没有超过最大值就会合并到一起

2.如果相邻的数据结构不同就按照结构体的方式计算

3.位段也是要对齐到对齐数的整数倍

 

位段不具有跨平台性,理由如下

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

 

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值