2. 位段(位段的填充&可移植性)
2.1 什么是位段:
1 .位段的成员必须是整形家族的成员(int,unsigned int,signed int ,char,unsigned char)
2 .位段的成员名后面有一个冒泡和一个数字。
3 .位段是可以节省空间的
为什么位段可以节省空间呢?
解释:
位段的位代表比特位,我们知道一个字节有8个比特位,当我们定义:
int flag = 1;实际上1只占用了一个比特位,但是int有四个字节,32个比特位,这就难免造成了空间上的浪费,因此利用位段可以节省这个不必要的开销。
比如:
struct A { //4byte-32bit int _a : 2; int _b : 5; int _c : 10; //15 //4byte-32bit int _d : 30; }; // //47 bit //6byte - 48bit //8byte - 64bit // int main() { printf("%d\n", sizeof(struct A)); return 0; }
- 那么如何求出A位段的大小呢?
2.2 位段求结构体大小的计算方法:
以上述代码为例,首先我们通过上面的学习认识到,结构体的大小是4*4=16的可能性最先被排除掉,由于引进后面的数字,使其变成相应比特位的大小,如果只是单纯的比特位相加,总和47个比特位,看成48个比特位,就是6个字节大小,但是,这么单纯的相加,也是不对的。计算方法如下:
先看类型,int ,4个字节,32个比特位,因此,由于是int类型,我们先给其4个字节大小,a,b,c一共用了2+5+10 = 17个比特位,而d占30个比特位,加上之后远远大于32个比特位,故我们在给其int大小,即四个字节,这样,由于d在之前的空间放不下,所以d不占用第一个int所给的空间,而是全部占用到第二个4字节中。故struct A的大小为八个字节。
2.3 位段的内存分配
1 位段的成员可以是int ,unsigned int ,signed int ,char(属于整形家族)类型
2 位段的空间上是按照需求以四个字节(int)或者一个字节(char)的方式来开辟的。
3 位段涉及很多不确定性因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
4 冒号后面比特位不能超过类型的大小。(char d : 14 是错误的)
当我们将其转化成二进制的时候,由于位段,需要舍弃其中的一部分比特位,当然,我们并不知道赋值放到内存中是从左到右还是从右到左,故我们假设是从右到左,二进制变成16进制,数字变成:62 03 04 。如上图,那么开始调试转成内存:(在VS编译器)
>故,我们的假设是正确的。
2.4 位段的跨平台问题
1 . int位段被当成有符号数还是无符号数是不确定的。
2 . 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大12,写成27,在16位机器会出现问题.)
3 .位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4 . 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的。
总结 : 跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在.
3. 枚举
3.1 枚举的使用:
enum Day//星期 { Mon,//0 Tues,//1 Wed,//2 Thur,//3 Fri,//4 Sat,//5 Sun//6 }; enum Day//星期 { //枚举常量 Mon=1, Tues, Wed, Thur, Fri, Sat, Sun };
3.2 枚举的优点:
- 增强代码的可读性和可维护性。
- 和#define定义的标识符比较枚举有类型检查,更加严谨。
- 防止命名污染(封装)。
- 使用方便,一次可以定义多个常量。
4. 联合(共用体)
4.1 联合类型的定义
联合也是一种特殊的自定义类型。
这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以联合也叫共用体)。
4.2 联合的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少有能力保存最大的那个成员)。
由于联合体的特性,共用一块空间,这就导致他们的首地址是相同的,当我们赋值时,也会由于覆盖的原因,后面赋值在公共的空间会将前面赋值的空间所覆盖,从而导致数的变化。
我们看到,u.c在u.a的后面赋值,则其会将对应公共的部分进行修改,刀子u.a变成了0x11223300,u.c = 0x00000000;当我们调换一下前后的位置时,发现:
u.a的公共部分将u.c的部分进行了修改,由此可见,联合体的公共部分是可以由后者改变前者的。
4.3 联合大小的计算
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
首先,对于数组的处理,不能将他看成是void [n]进行计算,对于Un1来讲,char c[5]应该看成char c1,c2,c3,c4,c5;因此占用5个字节,而int占用四个字节。
现在是五个字节,要变成最大类型的整数倍,因此sizeof(union Un1)的大小为8,;同理,Un2的大小为16.
5. 总结:
通过以上的对自定义类型的详解,可以让我们根据实际情况和具体的需求来节省空间和时间上的消耗,从而获得最大的效益。好了,本篇文章的分享到此结束了,码字不易,你们的支持将是我坚持的不竭动力。