#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stddef.h>
//int main()
//{
// //内置类型
// // 复杂对象:人书
// // 自定义类型——结构体、枚举、联合是自定义类型中用的比较多的
// //
// //
// //
// //
// //,结构也叫结构体,是一些值的集合,结构体的每个成员可以是不同类型的变量
// //数组是相同类型元素的集合
//
//
// //结构的声明
// //struct stu//tag表示结构体是干什么的
//
// //{
// // int age;
// // char name[];//member-list
// //}s1,s2;//viarable-list
// //是创建的struct stu类型的变量
// // 若放在大括号外,则是全局的结构体变量
// // 若放在大括号内,是局部变量
// //如上只是一个类型\
//
//
// //特殊类型声明
// // 匿名结构体类型
// /*struct
// {
// char name[];
// }s1, * p;
// struct
// {
// char name[];
// }x;*/
// //只能用一次,可以在声明的时候创建一个变量,用一次,不能多次使用
// // *p是结构体指针,若p=&x,则编译器会报错,因为在编译器看来,这是两种不一样的变量类型
// // 因为这是匿名结构体类型
// //
// //
// //
// //
// // 结构体的自引用
// //数据结构描述的是数据在内存中的存储结构
// //线形、顺序表(在内存中连续存放)、链表(一个节点放一个数和下一个节点)、树形、二叉树
//
// //设计链表节点
// //struct node
// //{
// // int data;//数据域
// // struct node *next;//指针域
// // //存放一个数据和下一个节点的地址
// // //结构体内部可以包含同类型的结构体指针,但是不能包含同类型的结构体
// //};
// /*typedef struct
// {
// int data;
// node* next;
//
// }node;*///要读匿名结构体类型重新起名叫node,typedef要求匿名结构体类型首先是存在的,才能对他重新起个名字,而这个类型又是对这个类型重命名产生的,就产生了先有鸡还是先有蛋的问题
// //解决方案
// typedef struct node
// {
// int data;
// struct node* next;
// }node;
// //结构体类型存在后,将其重命名为node ,以后在struct node s1就等价于node s2;
//
//
// //结构体的初始化
// struct point
// {
// int x;
// int y;
// }p1 = { 2,3 };
// //前面的类型相当于是通过图纸改了个房子,p1就是房子,同时进行赋值
// //多个元素初始化用大括号,若是结构体嵌套结构体,则大括号嵌套大括号
// //访问结构体类型.成员变量名
// //结构体枚举和联合
//
//
//
//
// //结构体内容对齐;
// struct S1
// {
// char c1;//1
// int i;//4
// char c2;//1
// };//成员顺序发生变化,大小也会发生变化
//
//
//
// // 1.第一个成员在与结构体偏移为零的地址处
// // 结构体开始存的字节后的第n个字节的偏移量是(n-1)
// // 2.其他成员变量要对齐到某个数字(对齐数)的整数倍地址处;
// // 对齐数等于编译器默认的对齐数与该成员变量大小的较小值
// // vs编译器默认的对齐数为八
// // 3.结构体大小为最大对齐数(每个成员变量都有自己的对齐数)的整数倍
// // 4.当结构体内部嵌套结构体时,存储位置对齐到被嵌套的结构体的最大偏移数的整数倍
// //
//
//
// //结构体为什么对齐存储
// // 1.平台原因(移植原因)
// // 不是所有平台都能访问任意地址上的任意数据的,某些硬件平台只能在某些地址出去某些特定类型的数据
// // ,否则抛出硬件异常
// // 2.性能原因
// // 数据结构(尤其是栈)应该尽可能在自然边界上对齐
// // 原因在于,为了访问未对齐的内存,处理器需要做两次内存访问;而对其的内存访问仅需做一次访问
// //
//
// //让占用空间小的成员尽量集中在一起
// //
// //
// //
// //
// // 修改默认对齐数
// // 用#pragma
// //
//
// struct S1 s1;
// printf("%zu", offsetof(struct S1,i));//offsetof(type,member)返回结构体成员大小,类型是size_t
// //offsetof是宏,需引头文件stddef
// //gcc编译器没有默认对齐数,只有vs编译器有默认字符数,其他的都是成员变量大小
// return 0;
//}
//修改默认对齐数
//#pragma pack(4)
//不需要默认对齐数是
//#pragma pack (1)
//结构体自引用类型本质上是指针,大小也是4/8字节