位段、枚举及联合
上一篇中主要将结构体的大小计算方式和内存对齐相关的知识整理了一下,但是C语言中还有结构体的几个“近亲”,他们就是位段、枚举以及联合。我们在学习他们的同时,不仅要清楚各自类型的特点,还要结合结构体在将他们放在一块进行比较对照,这样才能更好的将他们理解。那么我们就来看看这几个类型:
位段
一、位段的声明与结构体类似,但是还有几个不同点:
1.位段的成员必须是 (全部) int 或者 (全部) char(unsigned/signed)(不会有char和int同时出现)
2.位段的成员名后有个 ‘:’ 和 数字(数字表示该成员所占的bit位数)(存放内容时,根据bit位数发生截断)
3.若未指定成员大小,会开辟相应类型的空间大小 (如int a;开辟32个bit位)
4.若无成员变量名,只开辟相应数字的bit位,用来占用(填充)空间,该空间不能使用(eg:int :5;)
根据以上的特点,我们定义了两个不同的位段,并且通过画图的方式可以更直观的看到,两个位段中的成员在内存中的存储形式;
重要!!!位段类型大小的计算:
二、位段不跨平台的原因:
1. int 位段被当成有符号数还是无符号数,尚未确定
2. 不同机器的最大位数目不能确定
3. 位段中的成员在内存中存放时时从左向右分配还是从右向左分配未定义(vs中从右向左分配)
4. 当第二个成员所占内存较大,第一个位段中成员利用后剩余的空间舍弃还是利用(vs中舍弃)
三、位段的优缺点
优点:相比结构体,位段可以达到同样的效果,但更节省空间
缺点:不能跨平台使用
枚举
一、枚举类型的成员是对所描述内容的所有可能取值进行一一列举
注意:
1、枚举类型的大小都为4个字节(枚举变量只能取一个可能值 ,每个可能值都默认为一个整型数字)
2、对枚举变量进行n进行取值时,只能enum n = monday; 不能enum n = 0(不能用默认值赋值);
二、枚举的优点
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符相比,枚举有类型检查,更加严谨
3. 防止命名污染(命名冲突)
4. 便于调试
5. 使用方便,可一次定义多个常量
联合
一、联合的特点
联合的成员是共用同一块内存空间的(即所有成员占用内存时的起始地址是相同的)
二、联合大小的计算
1.联合的大小至少是最大成员的大小
2.当最大成员的大小不是最大对齐数的整数倍时,要对齐到最大对齐数的整数倍处。
三、 联合常被用于判断当前计算机的大小端存储方式
首先要知道什么是大小端?(觉得解释的比较好,就引用了一下)
大端模式:是指数据的高字节保存在内存的低地址中,而数据的低字节保存在内存的高地址中,这样的存储模式有点儿类似于把数据当作字符串顺序处理:地址由小向大增加,而数据从高位往低位放;这和我们的阅读习惯一致。
小端模式:是指数据的高字节保存在内存的高地址中,而数据的低字节保存在内存的低地址中,这种存储模式将地址的高低和数据位权有效地结合起来,高地址部分权值高,低地址部分权值低。
我在学习时看了概念之后,还是不能很好的理解,之后通过自己动手画出一个例子之后,瞬间就明白了。这样也更生动形象,易于理解。
四、联合和结构体的巧妙使用
这是我学习时遇到的一个很巧妙的代码(佩服这些大佬们!),自己也在vs2008中亲自实现了一下,并得到如下的结果:
下面是对上述代码的实现过程的描述:
也可判断出当前计算机的存储方式为小端存储
//内存是直接读取,数据则再以小端的方式读出
通过这段时间的学习,我认为对这几个类型的内存布局方式,不能只是仅仅记住规律就能掌握的,我觉得还是可以通过自己动手画图的方式,不仅可以将规律再熟悉一下,生动形象的将规律表现出来,我们的将更加深刻的理解并记忆。
毕竟有句名言说的好:实践是检验真理的唯一标准!!!