在C语言中有些数据在存储时并不需要占用一个完整的字节,只需要占用一个或几个二进制位即可,基于这种特殊的存储,C语言又提供了一种叫做位域的数据结构。
在结构体定义时,我们可以指定某个成员变量所占用的二进制位数(Bit),这就是位域
位段的声明和结构类似但是有两个不同
e.g.
1.位段的成员必须是 int、unsigned int 或signed int 。
2.位段的成员名后边有一个冒号和一个数字
struct bw{
unsigned m;
unsigned n: 4;
unsigned char ch: 6;
}
struct A
{
int _a : 2;
int _b : 5;
int _c : 10;
int _d : 30;
};
学会了如何声明之后相信有很多小伙伴是不是在思考,这个东东到底在内存中占多少空间呢??这里我们不妨来讨论一下:
printf("%d\n", sizeof(struct A));
通过我们的编译器(vs2019)能得到如下得结果
到这里相信很多小伙伴就以及开始犯糊涂了,这个结构体按照内存对齐原则根据偏移量来计算的话(4+4+4+4)应该为16,为什么结果却为8呢?下面我们来了解一下位段的存储规则
位域的具体存储规则如下:
到这里就不难解释为什么是8而不是16了:
struct A中有4个int 类型的变量,第一个int开辟出4个字节也就是32个bit,但是_a只占2个bit位,故_b占的5个bit也能够放入,_c所占10个bit也能够放入,到_c这一共放了17个bit,还剩下15个bit位,但是_d为30bit,显然放不进,故int _d向内存第二次申请4个字节的空间将30个bit全部放入,故最后的答案为8个字节!
——结构体,它就将不同类型的数据存放在一起,作为一个整体进行处理。
例如对于学生信息登记表,姓名为字符串,学号为整数,年龄为整数,所在的学习小组为字符,成绩为小数,因为数据类型不同,显然不能用一个数组来存放。
在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据。结构体是一种集合,它里面包含了多个变量或数组,它们的类型可以相同,也可以不同,每个这样的变量或数组都称为结构体的成员(Member)例如:
struct Stu
{
char name[20];//名字
int age;//年龄
char sex[5];//性别
char id[20];//学号
};//分号不能丢
接下来给大家介绍一下如何定义变量
#include
int main() {
struct {
char* name; //姓名
int num; //学号
int age; //年龄
} stu1;
//给结构体成员赋值
stu1.name = "zhoumin";
stu1.num = 1;
stu1.age = 18;
return 0;
}
在这里给大家介绍一下一个比较好玩的东西(枚举)enum
他的主要系统结构和结构体非常类似,枚举数据表的值都是整数。第一个枚举成员的默认值为整型的0,后续枚举成员的值在前一个成员上加1。也可以人为设定枚举成员的值,从而自定义某个范围内的整数。
enum Day//星期
{
Mon,//打印为0
Tues,//1
Wed,//2
Thur,//3
Fri,//4
Sat,//5
Sun//6
};
以上定义的 enum Day就是一个是枚举类型,{}中的内容是枚举类型的可能取值,也叫 枚举常量
这时候就有小伙伴要说了,我们可以使用 #define 定义常量,为什么非要使用枚举?
给大家介绍一下枚举的优点:
使用枚举可以一次定义多个变量,如果使用#define的方式要从Mon开始一个一个去定义七遍,显得是不是有点太浪费时间了?下面运用了枚举来处理这事情瞬间就变得非常简单了,一次性全部定义了,是不是很香呢?
#include
enum week {Mon=1,Tue,Wed,Thu,Fri,Sat,Sun};
int main()
{
printf("%d",Mon);
return 0;
}
联合也是一种特殊的自定义类型
结构体和共用体的区别在于:结构体的各个成员会占用不同的内存,互相之间没有影响;而共用体的所有成员占用同一段内存,修改一个成员会影响其余所有成员。
共用体也是一种自定义类型,可以通过它来创建变量,例如:
union data{
int n;
char ch;
double f;
};
union data a, b, c;
联合的成员是共用同一块内存空间的,修改一个成员会影响其余所有成员,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)。
# include
int main() {
union Un
{
int i;
char c;
};
union Un un;
// 下面输出的结果是一样的吗?
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
//下面输出的结果是什么?
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}
1.联合体union特性
联合体所有成员变量共享内存,相对于联合体首地址偏移量都为0
同一时间只能存储1个被选择的变量,对其他成员变量赋值会覆盖原变量
2.联合体大小计算准则
联合体大小要至少能容纳最大的成员变量
联合体大小要是所有成员变量类型大小的整数倍
#include
int main() {
union Un1
{
char c[5];
int i;
};
union Un2
{
short c[7];
int i;
};
//下面输出的结果是什么?
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));
return 0;
}
在清楚了上述的规则之后,我们来尝试运用一下,在union un1中我们可知至少要有51的空间,空间又必须为4的倍数,故sizeof(union un1)=8;再来看看union un2 中我们知道至少要有27的空间,空间又必须为4的倍数,故sizeof(union un2)=16;