一、位段
1.什么是位段?
位段的声明与结构体是类似的,但是有一些不同,位段的成员必须是int、unsigned int、signed int、char(数组整形家族类型),位段的成员名后边有一个冒号和一个数字。
示例:
struct A
{
int a:2;
int b:5;
int c:10;
int d:30;
};
2.位段的内存分配
①位段的成员都是属于整形家族的类型
②位段的空间上是按照需要以一个字节(char)或者四个字节(int)的方式来开辟的
③位段涉及很多不确定的因素,所以位段是不跨平台的,要注重可移值的程序应该避免使用位段
struct S{
char a:3;
char b:4;
char c:5;
char d:4;
};
printf("%d\n",struct S);
以上位段是如何在内存中存储的呢?我们现在VS下运行一下这个代码。
这是为什么呢?我们来画个图解释一下。
所以才存放位段A的时候,总共开辟了三次char所以位段A所占空间为3个字节。
3.位段的跨平台问题
①int位段被当成有符号数还是无符号数在不同平台下是不确定的
②位段中最大为的数目无法确定。(16位机器下最大的是16,32位机器下最大的是32,如果写成27,在16位的机器下就会出现问题)
③位段中的成员时从左向右分配还是从右向左分配的标准尚未定义
④当一个结构体包含两个位段,第二个位段成员比较大,无法容纳第一个位段剩余的位时,时舍弃还是利用,这是不确定的。
总结:跟结构体相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台问题的存在。
二、枚举
1.什么是枚举
枚举顾名思义就是意义列举,将所有的可能一一列举,比如:我们生活中的一周,以及月份,性别等等都可以一一列举。在这个时候就可以使用枚举了。
2.枚举类型的定义
enum Day
{
Mod,
Tues,
Wed,
Thur,
Fri,
Sat,
Sun
};
enum Sex
{
MALE,
FEMALE,
SECRET
};
以上定义的enum Day, enum Sex都是枚举类型。
{}中的内容是枚举类型的可能取值,也叫做枚举常量。这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。
示例:
enum Color
{
RED = 1,
GREEN = 2,
BLUE = 3
};
2.枚举的优点
①增加代码的可读性以及可维护性
②跟#define定义的标识符比较枚举有类型检查,更加严谨
③防止了命名污染
④便于调试
⑤使用方便,可以一次定义多个常量
3.枚举的使用
enum Color
{
RED = 1,
GREEN = 2,
BLUE = 4
};
enum Color clr = GREEN;//只能拿枚举常量来给枚举变量赋值
clr = 5;
三、联合体
1.联合体类型的定义
联合也是一种特殊的自定义类型,这种定义的变量也包含一系列的成员,特征是这些成员公用同一块空间,所以联合也叫共用体。
示例:
//联合体的声明
union Un
{
char c;
int i;
};
//联合变量的定义
union Un un;
2.联合体的特点
联合的成员是共用同一块内存空间的,这样一个联合体变量的大小,至少是最大成员的大小(因为联合体至少得有能力保存最大的成员)
示例:
union Un
{
int i;
char c;
};
union Un un;
//下面的结果一样吗?
printf("%d\n",&(un.i));
printf("%d\n",&(un.c));
我们发现是一样的,也就是验证了我们所说的,联合体内的所有成员公用一块内存空间,所以他们的起始地址是一样的。
由于联合体的这个特性,所以我们可以利用联合体来解决一个问题:
判断当前计算机的大小端存储:
union Un
{
int i ;
char c;
};
int main()
{
union Un un;
un.i = 1;
if( 1 == un.c )
{
printf("此计算机是小端存储\n");
}
else
{
printf("此计算机是大端存储\n");
}
return 0;
}
3.联合大小的计算
联合的大小至少是最大成员的大小,并且当最大成员的大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
union Un
{
char c[5];
int i;
};
printf("%d\n",sizeof(union Un));
因为char c占了五个字节,而int i只占有四个字节,由于联合体所有成员共用一块内存,所以给这个联合体五个字节就够了,但是由于这个联合体的最大对齐数是4,而5并不是4的倍数,所以此时联合体真正的大小应该是8.
联合与结构体的巧妙使用:
union ip_addr
{
unsigned long addr;
struct
{
unsigned char c1;
unsigned char c2;
unsigned char c3;
unsigned char c4;
}ip;
};
union ip_addr my_ip;
my_ip.addr = 176238749;
printf("%d.%d.%d.%d\n",my_ip.ip.c4,my_ip.ip.c3,my_ip.ip.c2,\
my_ip.ip.c1);
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!