C语言之联合和枚举

C语言之联合和枚举

文章目录

  • C语言之联合和枚举
    • 1. 联合体
      • 1.1 联合体的声明
      • 1.2 联合体的特点
      • 1.3 结构体和联合体对比
      • 1.4 联合体大小的计算
      • 1.5 联合体小练习
    • 2. 枚举
      • 2.1 枚举类型的声明
      • 2.2 枚举类型的优点
      • 2.3 枚举类型的使用

1. 联合体

1.1 联合体的声明

像结构体⼀样,联合体也是由⼀个或者多个成员构成,这些成员可以不同的类型。
但是编译器只为最⼤的成员分配⾜够的内存空间。联合体的特点是所有成员共⽤同⼀块内存空间。所以联合体也叫:共⽤体
给联合体其中⼀个成员赋值,其他成员的值也跟着变化

1.2 联合体的特点

代码一:

#include 

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	printf("%zd\n", sizeof(uu));
	return 0;
}

代码运行结果:>
4

结论:联合的成员是公用一块空间的,联合体变量的大小至少是最大成员的大小(至少确保能存下最大的那个成员)

代码二:

#include 

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	printf("%p\n", &(uu.a));
	printf("%p\n", &(uu.b));
	printf("%p\n", &uu);
	return 0;
}

代码运行结果:>
012FFD90
012FFD90
012FFD90

可以看到无论是联合体的地址还是联合体成员的地址都是一样的,说明他们共用同一块空间

代码三:

#include 

union U
{
	char a;
	int b;
};
int main()
{
	union U uu = { 0 };
	uu.b = 0x11223344;
	uu.a = 0x55;
	printf("%#x\n", uu.b);
	return 0;
}

%#x打印的是带0x的十六进制数,0x11223344是一个十六进制数

代码运行结果:>
0x11223355

C语言之联合和枚举_第1张图片
由于是小端字节序存储,优先存低字节的也就是44,然后通过char修改了第一个字节的内容,将44修改成了55,所以打印结果为0x11223355

1.3 结构体和联合体对比

union U
{
	char a;
	int b;
};
struct S
{
	char a;
	int b;
};

C语言之联合和枚举_第2张图片
相对于结构体,联合体较节省空间

1.4 联合体大小的计算

  1. • 联合体大小至少是联合体中最大成员的大小
  2. • 当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍,和结构体一样,联合体也是有对齐的
#include 

union U1
{
	char a[7];
	int b;
};
union U2
{
	short a[7];
	int b;
};
int main()
{
	union U1 u = { 0 };
	union U2 uu = { 0 };
	printf("%zd\n", sizeof(u));
	printf("%zd\n", sizeof(uu));
	return 0;
}

代码运行结果如下:>
8
16

联合体U1中有两个成员,char a[7] int b 其中最大成员为char a[7],为7个字节,char为1字节,默认对齐数为8,取较小值1,int为4字节,默认对齐数为8,取较小值4,所以两个成员中的最大对齐数为4,最大成员的大小为7,不是最大对齐数4的倍数,所以将对齐至8字节,对齐之后才是联合体的大小

同理联合体U2,也有两个成员,最大成员的大小为14字节,不是最大对齐数4的倍数,所以将对齐至16字节,对齐之后才是联合体的大小

1.5 联合体小练习

要求:写一个代码,判断当前机器的字节序

代码一:

#include 

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

小端字节序,将低字节内容存到低地址,高字节内容存到高地址
大端字节序,将高字节内容存到低地址,低字节内容存到高地址
内存使用优先使用低地址

1的十六进制为00 00 00 01
小端字节序为 01 00 00 00
大端字节序为 00 00 00 01

取出1的地址,将其从int类型的指针强制类型转化为char类型的地址,这样解引用的时候就会访问低地址处的内容,如果解引用得到1则是小端,得到0则为大端

代码二:
使用联合体的方式

#include 

int check_sys()
{
	union
	{
		char a;
		int b;
	}un;
	un.b = 1;
	return un.a;
}
int main()
{
	int ret = check_sys();
	if (ret == 1)
		printf("小端\n");
	else
		printf("大端\n");
	return 0;
}

通过联合体公用同一块空间的方式,如果第一个字节中存的是1则是小端,如果存的是0则是大端

2. 枚举

2.1 枚举类型的声明

枚举顾名思义就是一一列举

enum Day//星期
{
	Mon,
	Tues,
	Wed,
	Thur,
	Fri,
	Sat,
	Sun
};

枚举类型:enum Day
枚举常量:Mon,Thus,… //枚举常量使用逗号隔开,最后一个常量不需要

枚举常量是有值的,第一个常量的值默认从0开始,依次递增1,也可以在声明的时候为枚举常量赋值

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

2.2 枚举类型的优点

有#define关键字为什么还要使用枚举呢

  1. 增加代码的可读性和可维护性
  2. 和#define定义的标识符⽐较枚举有类型检查,更加严谨。
  3. 便于调试,预处理阶段会删除 #define 定义的符号
  4. 使⽤⽅便,⼀次可以定义多个常量
  5. 枚举常量是遵循作⽤域规则的,枚举声明在函数内,只能在函数内使⽤

2.3 枚举类型的使用

#include 

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

int main()
{
	enum Color clr = BLUE;//使用枚举常量为变量赋值
	return 0;
}
#include 

enum Color
{
	RED = 4,
	YELLOW = 8,
	BLUE = 12
};

int main()
{
	enum Color clr = 12;//使用整数为变量赋值,12 == BLUE
	return 0;
}

在C语言中,对其规定不是很严格,在C++中,C++的类型检查比较严格,这是个语法错误,无法使用整型对枚举变量赋值

你可能感兴趣的:(c语言,开发语言,联合体,枚举,字节序)