枚举?联合?拿捏了

    《清明》 杜牧
清明时节雨纷纷,路上行人欲断魂。
借问酒家何处有?牧童遥指杏花村。


前言

我们已经学习了结构体的基本知识,
现在来学一学其他数据形式。


一.概念

1.枚举

  枚举顾名思义就是一一列举。
  把可能的值一一列举。
  比如我们现实生活中:

 周一到周日,可以一一列举。
 一年十二个月,可以一一列举。

  如我们创建枚举变量Day,不进行赋值。

enum Day
{
	Monday,
	Tuesday,
	Wednesday,
	Thursday,
	Friday,
	Saturday,
	Sunday
};

在这里插入图片描述
  若我们在enum里对周三赋值,即 Wednesday = 5;
则周四变为5后面一个数6,周五、周六同理。
在这里插入图片描述

2.联合

  联合,又称为共用体
  联合是一种是一种特殊的自定义类型,包含一系列成员变量,特征是这些成员共用一块空间
  共用是如何体现的呢?
  我们执行以下代码:

union Un
{
	char c;//1
	int i;//4
};

int main()
{
	union Un u;
	printf("%p\n", &u);//打印联合体地址
	printf("%p\n", &(u.c));//打印c的地址
	printf("%p\n", &(u.i));//打印i的地址
}

  我们发现各成员的地址是一样的。
  这说明联合确实具有“共用”的特点。
  我们用图像来进一步理解。
在这里插入图片描述
  这时候细心的小伙伴就发现了。这不行呀!要是改了其中一个,另一个不也遭殃了吗?
  但倒也不必慌张,因为在同一时间,我们只用其中一个,这样即使更改了,也不会有任何影响。
  比方说,我们描述一个人的职业,在同一时间,我们只说他是老师,不会说他是老师,又说他是学生。

Tips
联合的成员是共用一块内存空间的,这样一个联合变量的大小最小是最大成员的大小。

二.为什么要用枚举和联合

1.枚举的优点

1.增加代码的可读性和可维护性
  
2.和#define定义的标识符相比,有类型检查,便于调试
  
3.防止了命名污染
  
4.使用方便,一次性定义多个常量

2.联合的优点

与结构体相比,联合体占用更少的内存空间。

三.枚举、联合使用实例

1.枚举变量注意事项

enum Day		
{
	Monday=1,
	Tuesday,
	Wednesday,
};

enum Day kite = Monday;

只能拿枚举常量给枚举变量赋值,才不会出现类型差异。
如以上给kite赋值是合法的,
如果直接写kite = 1则非法。

2.联合实现判断大小端

运用联合体,我们可以编写以下程序判断编译器的存储模式

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int check_cls()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i = 1;		//给i赋值1,此时c也被改变
	return u.c;		//若为小端,c为01
					//若为大端,c为00
}

int main()
{
	if (check_cls() == 1)
	{
		printf("小端\n");
	}
	else
	{
		printf("大端\n");
	}
}

3.联合大小的计算

  上文已经提到,联合体的大小至少是最大成员的大小。
  那么这个最大成员的大小是多少呢?
  我们看以下程序:

union Un
{	
	char arr[5];//5
	int i;//4
}u;

int main()
{
	printf("%d", sizeof(u));
}

乍一看,五个字节完全够用了,
可u的实际大小却是8个字节。
怎么会这样QAQ
这让我想起了联合体的好兄弟结构体
他的好兄弟哟,
满脑子都是内存对齐
这联合体,也是如此。
我们看他的成员,一个char类型的数组,对齐数要看其元素类型char,对齐数是1;一个是int类型的整型变量,对齐数是4,因此最大对齐数是4
为了放的下,最终大小对齐到8.

Tips
联合也存在内存对齐

来做道题检验一下学会了没有!!!

下面代码的结果是:( )
#include <stdio.h>
union Un
{
	short s[7];
	int n;
};
int main()
{
  printf("%d\n", sizeof(union Un));
  return 0;
}
//选项:
A .14
B .4
C .16
D .18

答案是C哦!

题解:联合体向int对齐,7个short一共是14字节,对齐后是16字节。n是单独的4字节,由于是联合体,n与s共用空间,只取最长的元素,故占用16字节。

四.几道经典例题

1.枚举

下面代码的结果是:( )

enum ENUM_A
{
		X1,
		Y1,
		Z1 = 255,
		A1,
		B1,
};
enum ENUM_A enumA = Y1;
enum ENUM_A enumB = B1;
printf("%d %d\n", enumA, enumB);
//选项:
A .1, 4
B .1, 257
C .2, 257
D .2, 5

本题答案为B,
注意到Z1赋值为255,
X1,Y1,Z1,A1,B1依次为0,1,255,256,257
在这里插入图片描述


2.联合

下面程序的输出是:()

#include<stdio.h>
int main()
{
  union
  {
    short k;
    char i[2];
  }*s, a;
  s = &a;
  s->i[0] = 0x39;
  s->i[1] = 0x38;
  printf(%x\n”,a.k);
  return 0;
}
//选项:
A .3839
B .3938
C .380039
D .不确定

答案是A哦
题解:如图,位顺序类似小端,低地址在低处,所以39是低地址,在低位,38在高位,所以是3839,故选A。
在这里插入图片描述

总结

  今天对枚举和联合进行了初步的讲解就结束啦!
  希望小伙伴们喜欢!!!OvO

  • 35
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 32
    评论
评论 32
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

二球悬铃木丶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值