自定义类型:【联合体和枚举】

一.联合体

1.联合体类型的声明

联合体像结构体一样,也是有一个或者多个成员组成,当然也可以不同的类型。但不同的是,比编译器只为最大的成员分配足够的内存空间,所有成员共用同一块内存空间。所以联合体也叫做:共用体。

联合体与结构体最不同的是,给联合体里的一个成员赋值,其他的成员也会随之变化。

联合体的声明其实也跟结构体大体一样

union Un
{
	char c;
	int i;
};
#include <stdio.h>
int main()
{
	union Un u = { 0 };
	printf("%zd", sizeof(u));
	return 0;
}

其实就是把struct给换成了union。

2.联合体的特点

上面的代码打印出来最终是4。可为什么是4呢?我们来探讨一下

首先,我们先思考一下,我上面说了一个东西就是所有成员共用一块空间。那么我在这个联合体里c和i的地址一样吗?我们来打印测试一下这两个地址是否一样。

其实是一样的。那么我们是不是可以得出一个结论:我们创建的一个成员变量i占了4个字节,这个c占了一个字节,其实i的第一个字节同样也是c的那一个字节。

再来看这个代码

union Un
{
	char c;
	int i;
};
#include <stdio.h>
int main()
{
	union Un u = { 0 };
	u.i = 0x11223344;
	u.c = 0x55;
	return 0;
}

再来看在内存中的存储,我改变了u.c的值,同样这里的44变成了55.

3.联合体大小的计算

想要计算联合体的大小,需要先明白两点

1.联合的大小至少是最大成员的大小

2.当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍

注意了,联合体的大小是至少是最大成员的大小,可不一定是最大成员的大小,举个例子:

#include<stdio.h>
union Un
{             //类型大小  默认对齐数  对齐数
	char c[5];//1         8        1
	int i;    //4         8        4
};
int main()
{
	union Un u = { 0 };
	printf("%d", sizeof(u));
	return 0;
}

打印出来的是8

因为c有5个char类型的元素。直接就占用了5个字节,根据上面的第二点,我们需要对齐到4的倍数,所以就是8.

4.联合体的使用

根据我前面所说的,使用联合体我们是可以节省空间的。

那么假如我们举行了一个游戏,参与游戏的人,获得了礼品兑换的机会。有三种商品我们可以兑换:图书,杯子和衬衫。而每一种商品都有:库存量,价格等其他信息。

还有一些商品的特有属性

图书:书名,作者,页数

杯子:设计

衬衫:设计,颜色,尺寸

如果我想用代码把这些结构写出来,如果不认真思考的话,可能就直接把这些一窝蜂的都写到结构体里去了。

可能写出来是这样的

struct gift_list
{
	//公共属性
	int stock_number;//库存量
	double price;//定价
	int item_type;//商品类型
	//特殊属性
	char title[20];//书名
	char author[20];//作者
	int num_pages;//页数

	char design[30];//设计
	int color;//颜色
	int sizes;//尺寸
};

根据我上次说的计算结构体大小的时候,这个占用的内存太多了,而且有一些属性其他的商品根本用不到。我们可以把一些特殊的属性给特殊的物品用,比如书名,作者和页数,这些属性只会给书本使用。那么我们就可以单独把一些单独的属性给列出来,其他有特殊属性的再单独用联合体在一起。

struct gift_list
{
	int stock_number;//库存量
	double price;//定价
	int item_type;//商品类型
	union
	{
		struct
		{
			char title[20];//书名
			char author[20];//作者
			int num_pages;//页数
		}book;
		struct
		{
			char design[30];//设计
		}mug;
		struct
		{
			char design[30];//设计
			int color;//颜色
			int sizes;//尺寸
		}shirt;
	}item;
};

在这里有一个联合体里面包含了三个结构体成员,我们把每一件物品的特属性都分别放在了book,mug和shirt里面,前提是当我们在使用其中一个的时候是不会影响其他的两个,这时我们就可以使用联合体的方式来很大程度的节省空间。

5.联合体的小练习

写一个程序来判断当前机器是大端还是小段

#include <stdio.h>
int check_sys()
{
	union Un
	{
		char c;
		int i;
	}u;
	u.i  = 1;
	return u.c;
}
int main()
{
	int ret = check_sys();
	if (ret = 1)
	{
		printf("是小端\n");
	}
	else
	{
		printf("是大端");
	}
	return 0;
}

可以复制来看一下打印出来的多少。

二.枚举类型

1.枚举类型的声明

所谓枚举,其实就是一一列举的意思。它的关键字是enum。比如三原色:

enum Color
{
	RED,
	GREEN,
	BLUE,
};

这就是把他们一一列举出来,{}里的内容也就是枚举类型的可能取值,也叫做枚举常量。枚举类型也是可以创建变量的,比如:

int main()
{
	enum Color color=RED;
	return 0;
}

值得注意的是,枚举内部的成员其实也有数值,我们可以单独打印出来它们的值来看一下。

#include<stdio.h>
enum Color
{
	RED,
	GREEN,
	BLUE,
};
int main()
{
	enum Color color=RED;
	printf("%d\n", RED);
	printf("%d\n", GREEN);
	printf("%d\n", BLUE);
	return 0; 
}

最终打印出来的值按顺序分别是0,1,2

我们在主函数里是不能改变这三个值的,因为它们也是常量。但是,我们可以在枚举体的内部改变它们的值:

我们把第二个值改了之后,这里的第二个值和第三个值也随之变化了。

2.枚举类型的优点

1.增加代码的可读性和可维护性

2.和#define定义的标识符相比枚举有类型检查,更加严谨(#define定义的标识符是没有类型可言的,但是枚举是有类型的,比如我给一个enum Color =RED;在c++中就不能写成enum Color =0,其实RED就是0)

3.便于调试,预处理阶段会删除#define定义的符号(在预处理的时候,如果代码里有#define定义的标识符,会直接给替换掉)

4.使用方便,一次可以定义多个常量

5.枚举常量是遵循作用域规则的,枚举声明在函数里,只能在函数里使用

感谢大家的观看,如果有错误,还请大家多多指正。

  • 27
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值