结构体
目录
一. 位段
1.概念
2.位段的内存分配
3.位段的跨平台问题
4.位段的应用
二. 枚举
1.枚举类型的定义
2.枚举的优点
3.枚举的使用
三. 联合(共用体)
1.联合类型的定义
编辑
2.联合的特点
3. 联合大小的计算
一. 位段
1.概念
位段的声明和结构是类似的,有两个不同:
1.位段的成员必须是 int、unsigned int 、signed int或char(本质上也属于整形) 。
2.位段的成员名后边有一个冒号和一个数字,而这个数字表示的是所占的二进制位数
例如
struct A
{
int _a:2;
int _b:5;
int _c:10;
int _d:30;
};
2.位段的内存分配
位段的空间上是按照需要以4个字节( int )或者1个字节( char )的方式来开辟的。
后面的数字不能大于类型的大小
位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段。
int main()
{
struct S
{
char a : 3;
char b : 4;
char c : 5;
char d : 4;
};
struct S s = { 0 };
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
return 0;
}
我们就用上面这代码来研究一下位段是如何进行内存分配的
首先,每个字节都有8位
顺着来看一下,首先是a,首先写出10的补码 00001010,然后将前三位(010)截断放进去
然后是b, 12的补码是00001100,将前四位(1100)截断放进去
然后是c,3的补码是00000011,将前五位(00011)放进去,但我们可以看到,这一个字节只剩下一位了,放不开五位,根据编译器的不同,有的会先存满这个字节,再存下一个字节,而有的会直接在下一个字节存储,而我使用的vs2022是第二种方式
最后的d也一样
最后就是这个样子
int 也差不多
3.位段的跨平台问题
1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。(16位机器最大16,32位机器最大32,写成27,在16位机器会出问题。)
3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时,是舍弃剩余的位还是利用,这是不确定的
4.位段的应用
二. 枚举
枚举顾名思义就是一一列举,把可能的取值一一列举。在之前的学习中也大致的提到过
1.枚举类型的定义
enum Color
{
RED,
GREEN,
BLUE
};
就是这么定义的
第一个取值默认为0,后面依次递增1,当然,我们可以改变任何位置的值,后面依旧是依次递增1
2.枚举的优点
枚举的优点:
1. 增加代码的可读性和可维护性
2. 和#define定义的标识符比较枚举有类型检查,更加严谨。
3. 防止了命名污染(封装)
4. 便于调试
5. 使用方便,一次可以定义多个常量
3.枚举的使用
只能拿枚举常量给枚举变量赋值,才不会出现类型的差异。
enum Color//颜色
{
RED=1,
GREEN=2,
BLUE=4
};
enum Color clr = GREEN;//right
clr = 5; //error
三. 联合(共用体)
1.联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)
例如
int main()
{
union Un
{
char c;
int i;
};
union Un un;
printf("%p\n", &(un.i));
printf("%p\n", &(un.c));
}
可以看到,两个成员的地址是相同的,这也就证实了成员是公用同一块空间的
2.联合的特点
联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大的那个成员)
int main()
{
union Un
{
int i;
char c;
};
union Un un;
un.i = 0x11223344;
printf("%x\n", un.i);
un.c = 0x55;
printf("%x\n", un.i);
return 0;
}
可以看到,在成员c改变时,i也会跟着改变
因此,我们也可以利用这一点来判断机器是大端还是小端
类似于上面,便是小端,而若是55223344,便是大端
3. 联合大小的计算
联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
第一点很好理解,毕竟联合的大小必须能够存放下每个成员
而第二点,举个例子
union Un
{
int i;
char c[5];
};
这个联合,最大的成员大小应该是c的5个字节,而最大对齐数应该是4(int),这时,我们便需要进行对齐,大小则应该为8