联合体与枚举以及结构体补充

1.结构体补充

昨天结构体有一些忘写了,让我们先把昨天的结束。

昨天讲了结构体的内存对齐,如果大家不知道这个重要的概念,可以去看这篇结构体内存对齐(你可能不知道但很重要的知识)-CSDN博客

内存对齐

上篇文章我们说了vs中默认对齐数是8,但是这个是可以改的,具体方法就是

#include<stdio.h>
#pragma pack(1)//将对齐数改为1
struct a {
	char a1;
	int a3;
	char a2;
	
};
#pragma pack()//还原为默认对齐数
struct b {
	char b1;
	int b3;
	char b2;
	
};
int main() {
	printf("%u\n%u", sizeof(struct a), sizeof(struct b));
}

同理在c++类中也一样:

cpp 复制代码
#include<iostream>
using namespace std;
#pragma pack(1)
class a {
	char a1;
	int a3;
	char a2;
	
};
#pragma pack()
class b {
	char b1;
	int b3;
	char b2;
	
};
int main() {
	cout << sizeof(a) << "\n" << sizeof(b);
	return 0;
}

结构体位段

  1. 位段的成员必须是 int、unsigned int 或signed int ,在C99中位段成员的类型也可以

选择其他类型。

  1. 位段的成员名后边有⼀个冒号和⼀个数字。
cpp 复制代码
#include<stdio.h>
struct A
{
	int _a : 2;
	int _b : 5;
	int _c : 10;
	int _d : 30;
};
int main() {
	return 0;
}

他的大小是多少呢?大家不妨猜猜看

为什么是8呢?我们需要先明白一个道理,他在类型后面加的数字相当于重新定义这个变量占几个比特,所以a占2个,b占5个,c占10个,d占30个,对于位段,我们有这样的规则

1. 位段的成员可以是 int , unsigned int , signed int 或者是 char 等类型。

2. 位段的空间上是按照需要以4个字节( int )或者1个字节( char )的⽅式来开辟的。

3. 位段涉及很多不确定因素,位段是不跨平台的,注重可移植的程序应该避免使⽤位段。

既然我们的数据类型是按int来开辟的,一次开辟4个字节,就是32个比特,a放进去,b放进去,c放进去,还有15个比特位没有放,但这时,已经不够放d了,所以我们重新开辟一个字节的空间去放d,所以最后大小就是8个字节

位段的弊端:

  1. int位段被当成有符号数还是⽆符号数是不确定的。

  2. 位段中最⼤位的数⽬不能确定。(16位机器最⼤16,32位机器最⼤32,写成27,在16位机器会

出问题。

  1. 位段中的成员在内存中从左向右分配,还是从右向左分配,标准尚未定义。4. 当⼀个结构包含两个位段,第⼆个位段成员⽐较⼤,⽆法容纳于第⼀个位段剩余的位时,是舍弃

剩余的位还是利⽤,这是不确定的。

总结:跟结构相⽐,位段可以达到同样的效果,并且可以很好的节省空间,但是有跨平台的问题存在。

2.联合体与枚举

1.联合体

cpp 复制代码
#include<stdio.h>
union u {
	char a;
	int b;
};
int main() {
	printf("%u", sizeof(union u));
	return 0;
}

联合体与结构体类似,声明的关键字是union,但区别就是,联合体是所有成员共用一片存储空间

接着我们把地址打出来可以发现,他所有元素的地址都一样,也证实了我们前面说的话

联合体的大小:

1.联合的⼤⼩⾄少是最⼤成员的⼤⼩。
2.当最⼤成员⼤⼩不是最⼤对⻬数的整数倍的时候,就要对⻬到最⼤对⻬数的整数倍。

cpp 复制代码
#include <stdio.h>
union Un1
{
	char c[5];
	int i;
};
union Un2
{
	short c[7];
	int i;
};
int main()
{
	//下⾯输出的结果是什么?
	printf("%d\n", sizeof(union Un1));
	printf("%d\n", sizeof(union Un2));
	return 0;
}

答案是8和16,why?首先先看un1,char数组占了5个字节,加上int共用还是5个,接着char的对齐数是1,int的对齐数是4,所以最后大小应是4的整数倍,就是8.

un2,short数组占14个字节,int占4个,共用14个,short对齐数是2,int是4,最后应是4的整数倍,所以最后是16.

联合体的使用最明显的优势就是节省空间了,⽐如,我们要搞⼀个活动,要上线⼀个礼品兑换单,礼品兑换单中有三种商品:图书、杯⼦、衬衫。每⼀种商品都有:库存量、价格、商品类型和商品类型相关的其他信息。

图书:书名、作者、⻚数

杯⼦:设计

衬衫:设计、可选颜⾊、可选尺⼨

然后我们写出了这样的代码:

cpp 复制代码
struct gift_list1
{
	//公共属性
	int stock_number;//库存量
	double price; //定价
	int item_type;//商品类型

	//特殊属性
	char title[20];//书名
	char author[20];//作者
	int num_pages;//⻚数

	char design[30];//设计
	int colors;//颜⾊
	int sizes;//尺⼨
};
struct gift_list2
{
	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 colors;//颜⾊
			int sizes;//尺⼨
		}shirt;
	}item;
};
int main() {
	printf("%u\n%u",sizeof(struct gift_list1), sizeof(struct gift_list2));
	return 0;
}

最后,我们尝试用联合体判断大小端。

cpp 复制代码
int check_sys()
{
 union
 {
 int i;
 char c;
 }un;
 un.i = 1;
 return un.c;//返回1是⼩端,返回0是⼤端
}

把un.i改为1,他的存储应该是00 00 00 01,如果是低位存储的话,应该此时char和int共用01这段空间,所以un.c也被改成了1,反之高位的话,char占据的是00的空间,是不变的。

2.枚举

枚举类型的关键字是enum

cpp 复制代码
#include<stdio.h>
enum sex {
	 male,
	 women,
	 secret
};

int main()
{

	return 0;
}

其中male代表0,women代表1,secret代表3,这个是默认的,当然我们也可以人为改变。

枚举的优点:

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

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

  3. 便于调试,预处理阶段会删除 #define 定义的符号

  4. 使⽤⽅便,⼀次可以定义多个常量

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

那我们是否可以用整形给枚举变量赋值呢?

在c语言中可以,但c++类型检查更加严格,就不行了

在c++中,

他就会报错

好的,就到这里了,大家中秋快乐鸭,有帮助的还请点个赞

相关推荐
Narutolxy1 分钟前
深入探讨 Go 中的高级表单验证与翻译:Gin 与 Validator 的实践之道20241223
开发语言·golang·gin
XiaoLeisj7 分钟前
【递归,搜索与回溯算法 & 综合练习】深入理解暴搜决策树:递归,搜索与回溯算法综合小专题(二)
数据结构·算法·leetcode·决策树·深度优先·剪枝
Hello.Reader8 分钟前
全面解析 Golang Gin 框架
开发语言·golang·gin
禁默19 分钟前
深入浅出:AWT的基本组件及其应用
java·开发语言·界面编程
yuyanjingtao22 分钟前
CCF-GESP 等级考试 2023年9月认证C++四级真题解析
c++·青少年编程·gesp·csp-j/s·编程等级考试
Jasmine_llq26 分钟前
《 火星人 》
算法·青少年编程·c#
Code哈哈笑29 分钟前
【Java 学习】深度剖析Java多态:从向上转型到向下转型,解锁动态绑定的奥秘,让代码更优雅灵活
java·开发语言·学习
程序猿进阶32 分钟前
深入解析 Spring WebFlux:原理与应用
java·开发语言·后端·spring·面试·架构·springboot
qq_4336184434 分钟前
shell 编程(二)
开发语言·bash·shell