结构体;
结构体类型
结构体分类
结构体变量定义和初始化
结构体传参
结构体位段
枚举;
枚举类型定义
枚举优点
枚举使用
联合;
联合类型定义
联合特点
联合大小计算
结构体声明
我们描述一个学生
struct stu
{
	char name[20];
	int age;
	char sex[10];/*性别*/
	char id[30];/*学号*/
};/*这个分号必须要*/特殊声明
我们可以省略结构体标签,这里省略了tap。
struct 
{
	char b;
	char c;
	int i;
}x;结构体的自引用
struct Node
{
	int data;
	struct Node* next;
};结构体变量的定义和初始化
我这里用了一个学生类型并初始化结构体
struct Stu
{
	char name[10];
	int age;
	char sex;
	char id[14];
};
int main()
{
	struct Stu s = { "liumeiling",20,"lv",1234567890 };/*结构体初始化*/
	return 0;
}结构体变量就比较简单,例如这段代码
struct tap
{
	char a;
	int b;
}t1;/*声明结构体并定义变量t1*/
struct tap t2  /*定义结构体变量t2*/另外对于嵌套式初始化也是比较好理解的
struct Point
{
	int x;
	int y;
};
struct Node
{
	int data;
	struct Point p;
	struct Node* next;
}n1 = { 9,{1,3}, NULL};/*结构体嵌套初始化*/
struct Node n2 = { 23,{7,8}, NULL }; /*结构体嵌套初始化*/然后我用一段代码演示一下结构体嵌套初始化
include<stdio.h>
struct T
{
	double high;
	int b;
};
struct S
{
	char name[20];
	struct  T st;
	int age;
	char id[30];
	
};
int main()
{
	struct S s  = { "liumeiling",{155.5},123456789098 };
	printf("%f\n", s.st.high);
	return 0;
}
结构体内存对齐
我们已经了解结构体的基础结构,那我们怎么计算结构体大小呢?这就要学习结构体对齐原理了。
结构体对齐规则;
1.第一个成员与在结构体变量偏移值为0的地址处。
2.其他成员要对齐到某个数字(对齐数)的整数倍的地址。(对齐数;编译器默认的一个对齐数与该整数倍的地址的较小值,VS中默认对齐数是8)
3.结构体中大小为最大对齐数(每个成员变量都有一个对齐数)的整数倍。
如果嵌套结构体,嵌套结构体对齐自己最大的对齐数倍数处,结构体大小就是所有最大对齐数的倍数。
struct S1
{
	int c1;
	int i;
	int c2;
};
struct S2
{
	char c1;
	char c2;
	int i;
};
struct S3
{
	double d;
	char c;
	int i;
};
struct S4
{
	char c1;
	struct S3 s3;
	double d;
};
int main()
{
	printf("%d\n", sizeof(struct S1));
	printf("%d\n", sizeof(struct S2));
	printf("%d\n", sizeof(struct S3));
	printf("%d\n", sizeof(struct S4));
	return 0;
}
修改默认对齐数
这里要用到预处理指令pragma,下面看代码就明白了。
#include<stdio.h>
#pragma pack(2) /* 设置默认对齐数为;2*/
struct S1
{
	char c1;
	int i;
	char c2;
};
#pragma pack(4)   /*设置默认对齐数为;4*/
struct S2
{
	char c1;
	int i;
	char c2;
};
#pragma pack()  /*取消设置默认对齐数,还原默认对齐数*/
struct S3
{
	char c1;
	int i;
	char c2;
};
int main()
{
	printf("%d\n", sizeof(S1));
	printf("%d\n", sizeof(S2));
	printf("%d\n", sizeof(S3));
	return 0;
}结构体传参
#include<stdio.h>
struct S
{
	int data[100];
	int num;
};
struct S s = { {1,2,3,4},100 };
//结构体传参
void print1(struct S s)
{
	printf("%d\n", s.num);
}
void print2(struct S* ps)
{
	printf("%d\n", ps->num);
}
int main()
{
	print1(s);   /*传结构体*/
	print2(&s);    /*传结构体地址*/
}对于print1,print2函数我们优先选择print2函数,函数传参的时候,会有时间和空间上的系统开销。
传结构体对象会出现结构体过大,系统开销比较大,导致性能下降。
所以结构体传参优先选择地址传参。
位段
位段和结构体你叫相同,单位段的成员必须是int,unsigned in和signed int 。并且位段成员后面有个数字和冒号。
struct B
{
	int _a : 2;
	int _b : 3;
	int _c : 7;
	int _d : 40;
};位段的内存分配
由于位段的成员都是 int,unsigned int, signed int,char。
位段的空间都是按四个字节或一个字节算的。
位段涉及很多不确定因素,位段是不跨平台。
枚举
就是列举的意识,把可能取得只列举出来。
比如性别有;男,女,保密;
星期;有周一到周日。
//枚举成员后面有的逗号
enum Day
{
	//下面叫枚举常量
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};并且枚举常量是有值的,默认从零开始,依次递增一,当然也可以给它赋值。
enum Color
{
	RED=2,
	GREEN=4,
	BLUE=6
};枚举的优点
1增加代码的可读性和维护性。
2 和#define定义的标识符比较枚举更有类型检查,更加严谨。
3 防止命名污染。
4 便于协调。
5 使用方便,一次可以定义多个常量。
联合体
联合体也是一个特殊自定义类型,这种类型包含了一系列成员,这些成员共用同一块空间。
特点是;联合体成员是共用一块空间,这样联合体大小至少是最大成员大小。
联合体计算
联合体大小至少是最大成员大小。
当最大成员不是最大对齐数的整数倍时,要对其最大对齐数整数倍。
#include<stdio.h>
union Un1
{
	char a[5];
	int a;
};
union Un2
{
	short a[7];
	int a;
};
int main()
{
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}









