目录
一、位段
1.什么是位段
2.位段的内存分配
3.位段的跨平台问题
二、枚举
1.什么是枚举
2.枚举的声明
3. 枚举类型的定义
4.枚举类型的初始化
5.枚举的优点
三、联合(共用体)
1.什么是联合
2.联合的声明
3.联合的定义
4.联合大小的计算
位段和结构是类似的,但是有两个不同:
①位段的成员必须是 int、unsigned int 、signed int或者是 char (属于整形家族)类型 。
②位段的成员名后边有一个冒号和一个数字。
③C语言允许在一个结构体中以位为单位来指定其成员所占内存长度,这种以位为单位的成员称为“位段”或称“位域”
struct A
{
int _a:2; //2个二进制位,分配2bit
int _b:5;
int _c:10;
int _d:30;
};
printf(“%d\n”,sizeof(struct A));这里会打印出什么?6还是8呢?
我们或许会认为是6,因为2+5+10+30=47bit≈6byte,但是位段的空间是4个4个字节(int)或者1个1个字节(char)开辟的。我们先开辟一个4byte,4byte=32bit,前面三个位段成员要分配2+5+10=17bit,32-17=15bit,但是最后一个位段成员需要30bit,15bit不够,所以我们还要再开辟一个4byte,一共8byte.所以位段A的大小为8byte
我们来看一条题:
#include
struct S
{
char a : 3;
char b : 4;
char c : 5;
char d : 6;
};
int main()
{
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
printf("%d\n", sizeof(struct S));
return 0;
}
编译并运行该代码,输出如下:
3
详细分析如下:
跟结构相比,位段可以达到同样的效果,但是可以很好的节省空间,但是有跨平台的问题存在。
一个集的枚举是列出某些有穷序列集的所有成员的程序,或者是一种特定类型对象的计数。比如:我们现实生活中: 一周的星期一到星期日是有限的七天,可以一一列举。
enum 枚举名
{
枚举成员列表
};
①enum 枚举名 变量名;
②enum 枚举名
{
成员列表;
}变量名列表;
#include
enum Color
{
RED,
GREEN,
BLUE //注意最后一个枚举常量没有","
};
enum Color
{
RED=2,//初始化
GREEN=4,
BLUE=8
};
int main()
{
printf("%d ", RED);
printf("%d ", GREEN);
printf("%d\n", BLUE);
printf("%d ", RED);
printf("%d ", GREEN);
printf("%d\n", BLUE);
//RED=8;//error,RED为枚举常量
enum Color c = GREEN;//只能拿枚举常量给枚举变量赋值,才不会出现类型的差异
if (c == GREEN)
{
printf("绿色\n");
}
return 0;
}
编译并运行该代码,输出如下:
0 1 2
2 4 8
绿色
{}中的内容是枚举类型的可能取值,也叫枚举常量 。 这些可能取值都是有值的,默认从0开始,一次递增1,当然在定义的时候也可以赋初值。
#define RED
#define GREEN
#define BLUE
PK
enum Color
{
RED,
GREEN,
BLUE
}
原因:①增加代码的可读性和可维护性
union 共用体名
{
共用体成员列表;
};
①union 共用体名 变量名;
②union 共用体名
{
成员列表;
}变量名列表;
共用体的成员共用同一块内存:
#include
union Un
{
char c;
int i;
};
int main()
{
union Un u = { 0 };
printf("%p\n", &u);
printf("%p\n", &(u.c));
printf("%p\n", &(u.i));
return 0;
}
编译运行该代码,输出如下:
三者地址相同,说明它们共用同一块空间
#include
union Un
{
char c[5];//1 8
int i;//4 8 成员中最大对齐数是4,但是最大的成员的大小为5,5不是4的倍数,下一个4的倍数是8,所以,要浪费3个空间
};
int main()
{
printf("%d\n", sizeof(union Un));//8
return 0;
}
5.利用联合,我们可以判断当前计算机的大小端存储:
#include
int main()
{
union U
{
char c;
int i;
}u;
u.i = 1;
if (u.c == 1)
{
printf("小端\n");
}
else
{
printf("大端\n");
}
return 0;
}