位段

位段(成员必须是整型) char也属于整型家族

struct S
{
	int _a : 2;//**代表a占两个字节,一个字节八个比特位**
	int _b : 5;
	int _c : 10;
	int _d : 30;
};
int main()
{
	printf("%d\n", sizeof(struct S));
	system("pause");
	return 0;
}

位段的内存分配
1.位段的成员可以是int,unsigned int或者signed int或者是char(属于整型家族)类型
2.位段的空间上是需要以4个字节(int)或者1个字节(char)的方式来开辟的
3.位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使用位段

struct S
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};
int main()
{
	struct S s = { 0 };  //very important!!!
	//printf("%d\n", sizeof(struct S));//3
	s.a = 10;
	s.b = 12;
	s.c = 3;
	s.d = 4;
	return 0;
}

枚举

标题和define的区别 #define 不能调试

enum Day
{
	Mon = 1,//0
	Tues,//1
	Wed,//2
	Thur,
	Fri,
	Sat,
	Sun
};
int main()
{
	enum Day day = Mon;**//初始化只能赋已有成员**
	day = Tues;
	printf("%d\n", Mon);
	printf("%d\n", Tues);
	printf("%d\n", Wed);
	printf("%d\n", Thur);
	return 0;
}

1.为什么要用枚举替换#define
(1)增加代码的可读性和可维护性
(2)和#define定义的标识符比较枚举有类型检查,更加严谨
(3)防止了命名污染
(4)便于调试,#define不可调试
(6)使用方便,一次可以定义多个常量

联合

union Un
{
	char i;//**成员共用一个空间**
	int c;
	double d;
};
int main()
{
	union Un u = { 0 };
	printf("%d\n", sizeof(union Un));//8
	printf("%p\n", &(u.c));
	printf("%p\n", &(u.i));
	printf("%p\n", &(u.d));
	return 0;
}

判断机器的大小端

普通方式

int check_sys()
{
	int a = 1;
	return *(char*)&a;
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端");
	}
	else
		printf("大端");
	return 0;
}

联合的方式判断

int check_sys()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;
	**//返回1,小端
	//返回0,大端**
	return u.c;//**取出第一个字节,类似于普通方法**
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
	return 0;
}

求联合的大小

union Un
{
	char c;
	int i;
};
union Un2
{
	short c[7];//short两个字节
	int i;
};
int main()
{
	printf("%d\n", sizeof(union Un));//8
	printf("%d\n", sizeof(union Un2));//16
	return 0;
}

(1)联合存在对齐
(2)联合的大小至少是最大成员的大小
(3)当最大成员不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍处