IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> C++知识库 -> 【C语言】自定义类型—位段、枚举、联合体 -> 正文阅读

[C++知识库]【C语言】自定义类型—位段、枚举、联合体

1.位段

什么是位段

位段的声明和结构体是类似的,但有两个不同的地方。

  1. 位段的成员必须是int,unsinged int 和signed int 或者是char(属于整型家族)类型
  2. 位段的成员名后有一个冒号和一个数字
    例如:
struct A
{
	int a : 2;
	int b : 5;
	int c : 10;
	int d : 30;
};
//struct A就是一个位段类型

那位段A的大小是多少?

printf("%d\n",sizeof(struct A));

位段类型struct A的大小
为什么是8呢?
在位段中:

位:二进制位

struct A
{
	int a : 2;//占2个bite位
	int b : 5;//占5个bite位
	int c : 10;//占10个bite位
	int d : 30;//占30个bite位
};
  • 4个成员变量都是int类型的,最开始只开辟4个字节的空间,然后在它们分别占用的比特位空间处放入数据
  • 最开始开辟4个字节,共32个bite位,a占2个,b占5个,c占10个,此时一共使用了17个bite位,还剩15个,d占30个,剩余不够d使用,在重新开辟4个字节将d放入其中,共使用8个字节。
  • 放入方式是固定的一种形式,下面便是我们对这种方式的学习。

位段的内存分配

  1. 位段的成员可以是int、unsigned int、signed int 或 char类型
  2. 位段的空间上是按照需要以4个字节(int)或1个字节(char)的方式来开辟的
  3. 位段涉及很多不确定因素,位段是不跨平台的,注意可以执行的程序应该避免使用位段。
  • 位段中int类型和char类型一般是不会混着用的,位段有很多的不确定性,所以我们在使用的时候一定要谨慎。

例子:

struct B
{
	char a : 3;
	char b : 4;
	char c : 5;
	char d : 4;
};
//char类型在位段存储中每次开辟一个字节
int main()
{
	struct B b = { 0 };
	b.a = 10;
	b.b = 12;
	b.c = 3;
	b.d = 4;

?	return 0;
}
  • 位段占据内存的规则
    在这里插入图片描述
  • 位段数据在内存中的存储
    在这里插入图片描述
  • VS调试展示内存
    在这里插入图片描述
    这些可以说明,在VS下
  • 位段开辟内存是按照成员变量的类型开辟空间的,当开辟的空间不够时,才会去增加1个对应类型大小的空间
  • 位段在内存中存储的方式是小端存储,由低地址向高地址存储数据
  • 分配方式是从右向左,从一个bite位的最低位开始存入数据。
  • C语言并没有规定这些规则,这些规则适用于VS编译器,不同的平台产生的效果是不同的,所以它是不支持跨平台的。

位段的跨平台问题

  1. int位段被看作有符号数还是无符号数是不确定的。
  2. 位段中最大位的数目不确定。(16位机器最大16,32位机器最大32)当我们把一个成员变量所占bite位写成27,在16位机器会出现问题。
    数据的顺序不变,接收的顺序不同。
  3. 位段中的成员在内存中从左向右分配,还是从右向左分配标准尚未定义.
    如果数据传输到不同平台的顺序相同,而分配和读取的方向不同,这明显是不对的
  4. 当一个结构包含两个位段,第二个位段成员比较大,无法容纳第一个位段剩余部分,是舍弃剩余的位还是利用,这是不确定的。
    总结:

位段可以达到和结构体相同的作用,而且可以更好的节省空间,但是有跨平台性的问题存在。

位段的应用

在这里插入图片描述

  • 使用位段式的结构合理的利用空间,将传输的数据分块给出固定的大小,减少数据的传输,提高数据传输的效率。

2.枚举

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

一周的星期一到星期日是有限的7天,可以一 一例举。
性别有:男、女、保密,也可以一 一列举。
月份有12个月,也可以一 一例句。
这里就可以使用枚举了。

枚举类型的定义

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

enum Day//星期
{
	MON,
	TUES,
	WED,
	THUR,
	FRI,
	SAT,
	SUN
};

enum Sex//性别
{
	MALE,
	FEMALE,
	SECRET
};

以上定义的enume Color,enum Day,enum Sex都是枚举类型。

  • 结构体大括号内的变量叫:结构体的成员变量
  • 枚举的大括号内是:枚举的可能取值也叫“枚举常量

因为它是常量,在定义枚举的大括号外,无法给它赋值。

在这里插入图片描述

这些可能取值都是有值的,默认从0开始,一次递增1

enum color
{
	RED,
	GREEN,
	BLUE
};

int main()
{
	printf("%d\n", RED);
	printf("%d\n", GREEN);
	printf("%d\n", BLUE);

	return 0;
}

在这里插入图片描述

在定义的时候也可以赋初值

enum color
{
	RED=1,
	GREEN=4,
	BLUE
};

int main()
{
	printf("%d\n", RED);
	printf("%d\n", GREEN);
	printf("%d\n", BLUE);

	return 0;
}

在这里插入图片描述

一个枚举类型的大小只有四个字节,每次取出的值为枚举的可能取值,它们不是同时在枚举类型中存储,一次只调用一种可能。(不同编译器下,枚举的大小可能会取不同的值)

enum color
{
	RED,
	GREEN,
	BLUE
};

int main()
{
	printf("%d\n", sizeof(enum color));

	return 0;
}

在这里插入图片描述

枚举的优点

我们可以使用#define定义常量,为什么非要使用枚举?

枚举的优点:

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

    当使用switch时可以将case后的选项替换为枚举的可能选择

  2. 和#define定义的标识符比较枚举有类型检查,更为严谨。

    #define定义的常量是直接替换掉,而枚举常量是有自己的类型的
    1.
    在这里插入图片描述
    2.
    在这里插入图片描述

  3. 防止了命名污染

    将枚举常量放在大括号中,对其进行封装防备受到污染。

  4. 便于调试

    枚举在调试中是可以直接看到的,而#define是直接替换
    在这里插入图片描述

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

3.联合(共用体)

联合类型的定义

联合也是一种特殊的自定义类型
这种类型定义的变量也包含一系列的成员,特征是这些成员共用同一块空间(所以联合也叫共用体)。

例如:

//联合类型的声明
union Un
{
	char c;
	int i;
};

//联合变量的定义
union Un un;

联合的特点

联合的成员是共用同一块内存空间的,这样一个联合变量的大小,至少是最大成员的大小(因为联合至少得有能力保存最大得那个成员)

union Un
{
	char c[5];
	int i;
};

int main()
{
	union Un un;
	printf("%d\n", sizeof(un));
	printf("%d\n", sizeof(un.c));
	printf("%d\n", sizeof(un.i));
	printf("%d\n", &(un.c));
	printf("%d\n", &(un.i));

	return 0;
}

在这里插入图片描述

  • 这里我们可以看到,不同类型的联合体成员的大小是不同的,但它们的地址却是相同的。这就是特征的表现——共用同一块内存空间。
union Un
{
	char c;
	int i;
};

int main()
{
	union Un un;
	un.i = 0x11223344;
	un.c = 0x55;
	printf("%x\n", un.i);
	printf("%x\n", un.c);

	return 0;
}

在这里插入图片描述

  • 当联合体一个成员的值发生改变会影响到其他成员在该空间的改变
  • 在联合体中的变量调用时最多只能有一个成员变量被调用,否则会使存储的数据变的很混乱。

联合大小得计算

  • 联合的大小至少是最大成员的大小
    最少要保证可以存储最大的成员的数据。
  • 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
union Un
{
	char c[7];//虽然c是个数组,但对齐数是以类型来所的,char类型对齐数为1,c总共占7个字节
	int i;//int类型对齐数为4
};

int main()
{
	union Un un;//默认对齐数为8,最大对齐数为4,取最小值4.
	printf("%d\n", sizeof(un));
    //最大的成员为c占7个字节,不是最大对其数4的整数倍,取最大对齐数的整数倍8,输出结果为8
    //而多余的一个空间是被浪费掉的,访问不到,非要访问可以使用数组,越界访问。

	return 0;
}

在这里插入图片描述

使用联合体判断大小端

在之前博客数据得存储中,讲到了判断大小端得方法,使用int和char的交换判断
这里我们使用新的方法重新判断

union Un
{
	int a;
	char b;
};

int main()
{
	union Un un;
	un.a = 0x1;
	int flag = un.b;
	if (flag == 1)
		printf("小端\n");
	else
		printf("大端\n");

	return 0;
}

在这里插入图片描述

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2022-09-25 23:05:06  更:2022-09-25 23:05:31 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 12:42:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码