自定义类型
一、结构体
1.匿名结构体类型
我们来举个例子介绍匿名结构体
1 | struct //创建时只有关键字,即为匿名结构体 |
再来列举一个匿名结构体常见的错误
1 | struct |
2.结构体的自引用
举个例子来看看结构体如何相互引用
1 | struct A |
那么结构体自引用是否为以下这种方式呢
1 | struct N |
正确方法如下
1 | struct N |
3.结构体的大小计算
结构体的对齐规则
1.第一个成员在与结构体偏移量为0的地址处
2.其他成员变量要对齐到(对齐数)的整数倍的地址处
.
对齐数 = 编译器默认的对齐数 与 该成员大小的较小值
VS默认为8(并且该默认值可以通过编码修改)
.
3.结构体总大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍
4.如果该结构体嵌套了另一个结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处
结构体整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍
我们以一张图来整明白这些话
前面提到过可以修改默认对齐数
以下
1 |
|
举个例子
1 |
|
二、位段
1.位段的介绍
位段的声明和结构体是类似的,但有两个不同
1.位段的成员必须是int、unsigned int 或 signed int
2.位段的成员后边有一个冒号和一个数字
例如
1 | struct A |
为什么好好的一个整形,偏要把它硬塞进2bit呢?
节省空间!!
比如说表示性别,2个字节就足矣
00 | 保密 |
---|---|
01 | 女 |
11 | 男 |
2.位段的大小
还是以上述代码举例子
1 | //2+5+10+30=47 |
但其实,在不同的环境下结果可能是不同的
比如在上述代码中,d塞不进去后,是继续用上一次留下的15bit,还是直接塞进新创建的呢?
所以说
位段涉及到很多不确定因素,位段是不跨平台的
注重可移植的程序应该避免位段
3.位段的实际使用情况
1 | struct S |
以上
4.位段跨平台问题
1.int位段被当成有符号数还是无符号数是不确定的
2.位段中的最大位的数目不能确定(16位机器最大16,32位最大32,若写成大于16的数再16位机器就会出问题)
3.位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义
4.当一个结构体包含两个位段,第二个位段成员比较大,无法容纳于第一个位段剩余的位时
—是舍弃剩余的位还是利用,这是不确定的
三、联合(共用体)
1.联合类型的定义
联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员
特征是这些成员共用一块空间(所以联合也叫共用体)
.
所以联合体的大小最小是最大成员的大小
2.利用联合特征判断机器大小端字节序
1 | int check_sys() |
3.联合大小的计算
联合大小最小是最大成员的大小
当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍
比如
1 | union Un |