http|自定义类型(那些容易出错的地方)

本讲主要内容
目录
1.结构体
2.位段
3.枚举
4.联合体(共用体)

1.结构体 1.1特殊的声明:匿名结构体声明

//匿名结构体 struct { int a; int b; char arr[10]; }x; struct { int c; int m; char arr1[10]; }*p;

上面的代码段定义了两个匿名结构体,但是编译器认为上面的两个结构体是不同的类型
所以下面这段代码是非法的
*p=&x;

1.2结构体的自引用
同类型找到同类型的节点的写法是错误的

struct stu { int a; char b; struct stu n };

原因:向上图对结构体进行自引用会使函数无限嵌套下去,会消耗极大的内存
正确的用法
struct stu { int a; char b; //上面被称为数据域 struct stu *p //指针域 };

指针只占4/8个字节的内存,而且能够找到下一个节点
结构体自引用不能省略名字

typedef struct { int a; char b; struct node *n }node;

这里把一个匿名结构体重命名为node,为什么上图的做法是非法的呢?
因为在结构体指针=出现了node,而在之前并没有对node进行命名,所以会报错,如何修改
typedef struct node { int a; char b; node* n }node;

先把匿名结构体命名为node,在用结构体指针进行自引用,所以,当我们对结构体进行传参的时候,传的都是结构体的地址,而不是结构体(&结构体变量名)
1.3结构体的内存对齐
结构体内存对齐是结构体的最大难点,根据结构体的对齐规则对结构体进行内存大小的计算
规则:http|自定义类型(那些容易出错的地方)
文章图片
?
struct stu { int a; double b; int c; };

如何计算上图中结构体的大小
根据规则画出内存图http|自定义类型(那些容易出错的地方)
文章图片
?
总的来说,结构体的内存是拿空间换取时间的做法;
如果想更加节省空间,可以让空间小的成员尽量集中在一起。
2.位段 什么是位段?
位段的声明和结构体类型,有两点不同
1.位段的成员必须是int,unsigned int这一种,或者char
2.位段的成员名后面必须要有一个冒号和数字
struct A { int a : 2; int b : 10; int c : 30; };

A就是一个位段类型,在32为编译器条件下,单个成员的位段不能大于32,上图中的2,10,30指的都是二进制位的意思;
这个位段的大小怎么求呢?
位段是一次开辟一个int型,即一次开辟四个字节,如果是char,就一次开辟一个字节,
所以a和b一共占了12个二进制位,但是c需要30个二进制位,所以要重新开辟4个字节,所以,该位段多占大小是8个字节
3.枚举的易错点
enum color//枚举类型 { RED,//枚举常量 GREEN, WHITE, };

RED是默认为·,一次递增1,当然可以对枚举常量进行赋值。
枚举的优点:1.增加代码的可读性和可维护性
2.使用方便,一次可以定义多个变量
3.防止命名污染
4.便于调试
5.和#define对比有类型检查,更加严谨
枚举的赋值:只能那枚举的常量给枚举的变量赋值
enum color { red=1, white=10, black=15, }enum color red=white; //这样赋值是正确的 white=10; //非法

4.联合体(共用体) 为什么叫联合体?
一位联合体成员都共用同一块内存
4.1联合体的大小怎么确定?
规则:当最大成员大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍;
http|自定义类型(那些容易出错的地方)
文章图片
?


【http|自定义类型(那些容易出错的地方)】

    推荐阅读