【C语言】枚举和联合

枚举

引入

        对于一周中的七天,为每个天数定义一个别名,在使用的时候用别名就知道是第几天。

        对于上述问题,很容易就想到用宏定义来实现,如下:

#define Mon 1

#define Tue 2

#define Thu 3

#define Wed 4

#define Fri 5

#define Sat 6

#define Sun 7

        但是宏名太多会导致代码比较松散,看起来总感觉不舒服,c语言提供了一种枚举类型(enum),能够列出所有可能取值,并给他们去取一个名字。

枚举的定义和格式

        枚举定义的语法格式和结构体类似,区别只在于,每一个枚举元素后面都是逗号,最后一个枚举元素后面无符号,其他定义格式都和结构体差不多:

enum 枚举名

{

     枚举元素1,

     枚举元素2,

     ……

};

         用枚举来实现上述问题。因为枚举类型里面,第一个元素默认值是0,后面的元素默认值依次+1,所以在这里把首元素的值改成1,那么该类型的元素取值依次是1-7,符合要求:

enum day
{
   Mon=1,
   Tue,
   Thu,
   Wed,
   Fri,
   Sat,
   Sun
};

枚举元素的取值/枚举常量

        运行下面一段代码,结果如下,不难发现,在定义枚举类型时,如果里面的枚举元素的值不作修改,那么就默认从0开始,依次加1,对应下方的运行结果就是:0-4。但是如果某一个枚举元素的值修改了,那么对这个枚举元素前面的枚举元素没有影响,比如Sat改成了10,但是对前面Mon到Fri的值无影响,只影响了后面的枚举元素的值,后面依然是依次+1。

#include<stdio.h>

enum Day
{
	Mon,
	Tue,
	Wen,
	Thu,
	Fri,
	Sat=10,
	Sun
};

int main()
{
	printf("%d\n", Mon);
	printf("%d\n", Tue);
	printf("%d\n", Wen);
	printf("%d\n", Thu);
	printf("%d\n", Fri);
	printf("%d\n", Sat);
	printf("%d\n", Sun);
	return 0;
}

   

        枚举元素又被称作枚举常量,既是常量,那么在使用的时候无法修改 ,如下,依然是上面的枚举,但是我在使用的时候,想要改变其中Thu的值,这个时候它产生错误,并且提示“表达式必须是可修改的左值”,那么印证了Thu是不可修改的:

枚举的应用

        枚举在switch语句里面应用较多,比如下方代码,用枚举元素red,green,blue来代替1、2、3:

#include <stdio.h>
#include <stdlib.h>
enum color 
{ 
   red=1, 
   green, 
   blue 
};

int main()
{
    enum  color favorite_color;
 
    /* 用户输入数字来选择颜色 */
    printf("请输入你喜欢的颜色: (1. red, 2. green, 3. blue): ");
    scanf("%u", &favorite_color);
 
    /* 输出结果 */
    switch (favorite_color)
    {
    case red:
        printf("你喜欢的颜色是红色");
        break;
    case green:
        printf("你喜欢的颜色是绿色");
        break;
    case blue:
        printf("你喜欢的颜色是蓝色");
        break;
    default:
        printf("你没有选择你喜欢的颜色");
    }
    return 0;
}

        此外,枚举可以用来判断机器是大端存储模式还是小端存储模式。比如下方代码,把1赋值给u.b,那么如果是大端存储,内存从低位到高位应该是 00 00 00 01,如果是小端存储,内存从低位到高位应该是 01 00 00 00。这个时候只看第一个字节的内容就可以,而char类型的数据正好是只存一个字节的空间,所以用联合里的a成员来读取数据,判断大小端。如下,VS2019是小端存储,正确。 

#include<stdio.h>

//在判断机器大小端方面的应用
union  
{
	char a;
	int b;
}u;  //匿名联合

int main()
{
	u.b = 1;
	if (u.a == 0)
		printf("大端!\n");
	else
		printf("小端!\n");
	return 0;
}

 

联合(共用体)

        联合也是一种特殊的自定义类型,其定义格式和struct类似,只不过最开始的sturtc 改成了union 。这种类型定义的变量也包含一系列的成员,特征是这些成员公用同一块空间(所以联合也叫共用体)。

特征

        联合,又被称作共用体,是因为其所有成员共同使用一块空间。通过以下的代码不难看出。并且这块空间的大小,是联合的所有成员里面,最大的数据类型的大小(联合也要对齐)。

#include<stdio.h>

//所有成员共用一块内存
union un
{
	double b;
	int a;
};

int main()
{
	union un ab = {128};
	printf("%p\n",&ab.a);
	printf("%p\n", &ab.b);
}

初始化

        《C和指针》关于“联合”一章中提到“联合变量可以被初始化,但这个初始值必须是联合第1个成员的类型”。

         比如下方的代码,运行结果如下,不难发现,初始化的时候,128是初始化的ab.a而不是ab.b,至于为什么ab.b打印出来是0.000000,也不难理解,由于是初始化的ab.a,所以按照整形的存储规则来,VS2019下是小端存储模式,此时用浮点数的方式读取这个数据时,浮点数存储有效数字的区域都是0,所以打印ab.b会是0.000000。(关于整形和浮点型数据存储规则,可以看(80条消息) c语言中数据的存储_Austerlitzl的博客-CSDN博客

#include<stdio.h>

//所有成员共用一块内存
union un
{
	int a;
	double b;
};

int main()
{
	union un ab = {128};
	printf("%d\n", ab.a);
	printf("%f\n", ab.b);
    printf("%d\n",sizeof(union un));
}

         我们将位置互换一下,可以发现正合我们的预期,这次的初始值是ab.b的类型,而不是ab.a的类型:

#include<stdio.h>

//所有成员共用一块内存
union un
{
	double b;
	int a;
};

int main()
{
	union un ab = {128};
	printf("%f\n", ab.b);
	printf("%d\n", ab.a);
}

对齐 

        和结构体的内存对齐一样,联合也要对齐。如下,联合test里面,第一个成员是一个数组,占14个字节大小,第二个成员是int类型变量,占4个字节大小。同时,第一个成员对齐数是2,第二个成员对齐数是4,所以test对齐数是4,最终占16个字节。运行截图如下。

#include<stdio.h>

union test
{
	short a[7];
	int b;
};

int main()
{
	printf("%d \n", sizeof(union test));
    return 0;
}

 

        关于枚举和联合的内容就介绍到这里!!!喜欢的话请一键三连哦!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

努力努力再努力.xx

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

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

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

打赏作者

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

抵扣说明:

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

余额充值