自定义类型:结构体,枚举,联合体
结构体的基础知识
结构体是一些值的集合
struct tag
{
  member_list;
}variable-list;struct Stu
{
  char name[20];
  int age;
  double score;
};
struct Book
{
  char name[20];
  float price;
  char id[12];
};
struct Stu s1;//全局
int main()
{
  struct Stu s2;//局部
  return 0;
}特殊的声明
struct   //匿名结构体 ,这里只能用一次
{
  char name[20];
  char id[12];
}ss;
struct   
{
  char name[20];
  char id[12];
}a[20],*p;
// p = &ss //err  匿名结构体的成员如果一样,在编译器看来也是不同的类型的结构体结构的自引用
数据域:存放数据的区域
指针域:存放下一个节点的地址
struct Node
{
  int data;//数据
  //struct Node n;//error
  struct Node * next;//最后一个地址是NULL
};
typeof struct Node   //typeof 是类型重命名
{
  int data;
  struct Node* next;
}Node,* pNode;
//pNode --> struct Node*
int main()
{
  struct Node n1;
  Node n2; //n2与n1类型一样
}结构体创建与初始化
struct Book
{
  char name[20];
  float price;
  char id[20];
}s={"c语言",55.5f,"PGC001"};
struct Node
{
  struct Book b;
  struct Node* next;
};
int main()
{
  struct Book s2 = {"love2study",66.6f,"bbd"};
  struct Node n = {{"Java",66.8,"TG001"},NULL};
  
  return 0;
  
}结构体内存对齐
-  第一个成员放在结构体内存偏移量为0的地址处 
-  其他成员要对齐到某个数字(对齐数)的整数倍的地址处 对齐数 = 编译器默认的一个对齐数与该成员大小的较小值 
-  结构体的总大小必须为最大对齐数(每个成员变量都有自己的对齐数)的整数倍 
-  如果嵌套了结构体,嵌套的结构体对齐到自己的最大对齐数的整数倍处,结构体的整体大小就是所有最大对齐数(含嵌套结构体的对齐数)的整数倍。 
struct S1
{
  char c1;
  int i;
  char c2;
};//12个字节
struct S2
{
  char c1;
  char c2;
  int i;
};//8个字节
//offsetof   //<stddef.h>
//size_t offsetof( structName, memberName );
//计算结构体成员相对于起始地址的便宜量修改默认对齐数
#pragma pack(4)//设置  一般2的几次方
struct S
{
  char c;
  double d;
};
#pragma pack()//取消  中间的结构体就是按照更改的对齐数来排序位段
-  位段的成员必须是int,unsigned int ,signed int. 
-  位段的成员名后边有一个冒号和一个数字。 
struct A
  {
    int _a:2;  //_a这个成员只占2个bit位
    int _b:5;  //_b这个成员只占5个bit位
    int _c:10; //_c这个成员只占10个bit位
    int _d:30; //_d这个成员只占30个bit位
  };
位段的开辟空间
-  位段的成员可以是int,unsigned int,signed int 或者是char类型 
-  位段的空间上是按照需要以四个字节(int)或者是1个字节(char)的方式来开辟的。 
-  位段涉及很多不确定因素,位段是不跨平台的,注意可移植的程序应该避免使用位段。 
枚举
enum Sex
{
   MALE,//0
   FEMALE,//1
   SECRET,//2
};// 枚举的可能
enum Day
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun,
};
int main()
{
  enum Sex s = MALE;
  enum Sex s2 = FEMALE:
  enum Day d =Fri;
}
// 枚举的值: 默认是从0开始,一次递增1,定义的时候也可以赋初值
联合(共用体)
联合的定义
包含一系列的成员,这些成员共有一块空间
nion Un
{
	char c; //1
	int i;  //4
};
int main()
{
  union Un u;
  printf("%d\n",sizeof(u));//4
  printf("%p",&u);
  printf("%p",(&u.c));
  printf("%p",(&u.i));
  //三个地址值相同
  return 0;
}
// 不会同时出现的时候可以选择联合体联合的特点
利用联合体判断大小端:
int check_sys()
{
  union Un
  {
    cahr c;
    int i;
  };
  c.i = 1;
  return u.c;
}
int main()
{
  if (1 == check_sys())
    printf("小端\n");
  else
    printf("大端\n")
  return 0;
}联合体也存在内存对齐的情况
union Un
{
	char arr[5];//看类型,都是1
	int i;
};//内存是8个字节,存在内存对齐









