【C语言进阶】讲解自定义类型(位段&枚举&联合)

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

目录

前言

一、位段

1 、什么是位段

 2、 位段的内存分配

​编辑

 3 、位段的跨平台问题

二、枚举

1 、枚举类型的定义

 2 、枚举的优点

3 、枚举的使用 

四、 联合共用体

1 、联合类型的定义

2、联合的特点

3 、联合大小的计算


 

前言

上节课我们学习了自定义类型中的结构体但是自定义类型中可不止结构体一种接下来让我们看看自定义类型中的其他形式吧。

一、位段

讲完结构体之后我们就必须来讲讲结构体实现 位段 的能力。

1 、什么是位段

位段C语言允许在一个结构体中以位为单位来指定其成员所占内存长度这种以位为单位的成员称为“位段”或称“位域”( bit field) 。利用位段能够用较少的位数存储数据。

位段的声明和结构是类似的有两个不同
1. 位段的成员必须是 int unsigned int signed int
2. 位段的成员名后边有一个冒号和一个数字。
3.位段中的成员类型是相同的。
我们先来看这段代码
struct A
{
 int _a:2;
 int _b:5;
 int _c:10;
 int _d:30;
};
printf("%d\n", sizeof(struct A));

例如上边的代码与结构体类似使用struct关键字进行位段操作时在成员名后加上冒号的数字这个数字就是我们需要位段的位数注意这里是二进制位。

所以A就是一个位段类型所以我们来计算一下A的大小。

首先我们看到成员的类型为int型当我们存储数据时先申请四个字节的空间即32个比特位。

 2、 位段的内存分配

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;
};
struct S s = {0};
s.a = 10;
s.b = 12;
s.c = 3;
s.d = 4;
//空间是如何开辟的

 我们知道了在存储数据时可以进行位段操作可以节省很多空间接下来我们就探究一下空间是如何开辟的。

 3 、位段的跨平台问题

1. int 位段被当成有符号数还是无符号数是不确定的。
2. 位段中最大位的数目不能确定。16位机器最大1632位机器最大32写成27在16位机
器会出问题。
3. 位段中的成员在内存中从左向右分配还是从右向左分配标准尚未定义。
4. 当一个结构包含两个位段第二个位段成员比较大无法容纳于第一个位段剩余的位时是
舍弃剩余的位还是利用这是不确定的。
总结
跟结构相比位段可以达到同样的效果但是可以很好的节省空间但是有跨平台的问题存在。

二、枚举

在数学和计算机科学理论中一个集的枚举是列出某些有穷序列集的所有成员的程序或者是一种特定类型对象的计数。这两种类型经常但不总是重叠 是一个被命名的整型常数的集合枚举在日常生活中很常见例如表示星期的SUNDAY、MONDAY、TUESDAY、WEDNESDAY、THURSDAY、FRIDAY、SATURDAY就是一个枚举。

1 、枚举类型的定义

enum Day//星期
{
 Mon,
 Tues,
 Wed,
 Thur,
 Fri,
 Sat,
 Sun
};
enum Sex//性别
{
 MALE,
 FEMALE,
 SECRET
}
enum Color//颜色
{
 RED,
 GREEN,
 BLUE
};

enum是枚举类型的关键词与结构体声明时相似使用枚举关键字enum加标签来声明。

以上定义的 enum Day enum Sex enum Color 都是枚举类型。 {}中的内容是枚举类型的可能取值也叫 枚举常量

这些可能取值都是有值的默认从0开始一次递增1当然在定义的时候也可以赋初值。

例如下边的代码

enum Color//颜色
{
 RED,
 GREEN,
 BLUE
};

当我们不给枚举常量赋值时枚举常量就按照顺序从0开始递增。

当我们给其中一个枚举常量赋值时从这个常量后边的值都依次递增。

enum Color//颜色
{
	RED ,
	GREEN=3,
	BLUE
};

 

 2 、枚举的优点

我们可以使用 #define 定义常量为什么非要使用枚举
例如
#define RED 1
#define GREEN 2
枚举的优点
1. 增加代码的可读性和可维护性
2. #define 定义的标识符比较枚举有类型检查更加严谨。
3. 防止了命名污染封装
4. 便于调试
5. 使用方便一次可以定义多个常量

当我们使用枚举类型之后可以清楚的看到一个类型里边到底有几类东西例如我们的颜色枚举类类型中我们可以清晰的看到有红绿蓝三种颜色而且在我们调试的时候由于#define 定义的常量是预处理阶段就进行了替换所以在生成.exe文件之后我们进行调试虽然我们看到是常量名但是早已替换为数字所以不便于调试。

3 、枚举的使用 

我们来看下边的代码

enum Color//颜色
{
 RED=1,
 GREEN=2,
 BLUE=4
};
enum Color clr = GREEN;//只能拿枚举常量给枚举变量赋值才不会出现类型的差异。
clr = 5;               //ok??

我们定义一个枚举类型的变量 clr 使用枚举常量来赋值是可以的但是这时就有人说既然一个常量对应一个数那我们是否可以直接用数字来赋值呢?答案是不可以因为这样会出现类型的差异使用枚举常量给枚举变量他们都是枚举类型才不会出错。

四、 联合共用体

在进行某些算法的C语言编程的时候需要使几种不同类型的变量存放到同一段内存单元中。也就是使用覆盖技术几个变量互相覆盖。这种几个不同的变量共同占用一段内存的结构在C语言中被称作“共用体”类型结构简称共用体也叫联合体。

联合体的关键字是union他与结构体枚举的声明类型都是相似的都是通过关键字加类型名来定义的。

1 、联合类型的定义

//联合类型的声明
union Un
{
 char c;
 int i;
};
//联合变量的定义
union Un un;
//计算连个变量的大小
printf("%d\n", sizeof(un));

2、联合的特点

联合的成员是共用同一块内存空间的这样一个联合变量的大小至少是最大成员的大小因为联
合至少得有能力保存最大的那个成员。但是一个联合变量的大小有时也比最大成员的大小要大。
union Un
{
int i;
char c;
};
union Un un;
// 下面输出的结果是一样的吗
printf("%d\n", &(un.i));
printf("%d\n", &(un.c));
//下面输出的结果是什么
un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

 我们发现unun.iun.c他们的地址都是一样的所以这样可以证明联合都是使用一块空间的当我们使用谁时谁占有这个空间。

面试题  

判断当前计算机的大小端存储
union Un
{
	int a;
	char b;
};
int main() {
	union Un un;
	un.a = 1;
	if (un.b == 1) {
		printf("小端\n");
	}
	else {
		printf("大端\n");
	}
	return 0;
}

3 、联合大小的计算

联合的大小至少是最大成员的大小。
当最大成员大小不是最大对齐数的整数倍的时候就要对齐到最大对齐数的整数倍。
比如
union Un1
{
 char c[5];
 int i;
};
union Un2
{
 short c[7];
 int i;
};
//下面输出的结果是什么
printf("%d\n", sizeof(union Un1));
printf("%d\n", sizeof(union Un2));

首先我们看到Un1中有一个char类型的数组其中有五个元素所以所需空间为五个字节int类型为四个字节所以为了存放他们至少需要五个字节的空间但是在联合中最大对齐数为int的四个字节必须对齐到最大对齐数的整数倍所以为8个字节。

在Un2中有一个short类型的数组有7个元素所有需要14个字节的空间int型需要四个字节又因为最大对齐数为4所以联合体的大小为16个字节。


 本节完 ……

 

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

“【C语言进阶】讲解自定义类型(位段&枚举&联合)” 的相关文章