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 结构体的特殊声明(匿名结构体类型)

struct
{
	int a;
	char b;
}x;

struct
{
	int a;
	char b;
}y;

上面的例子中省略了结构体标签

x = y;//将y中的成员赋值给x中的成员

尽管两个匿名结构体有相同的成员,但是编译器仍然将它们视为不同的两个构造体类型,因为它们是匿名的。

匿名结构体类型只可以用一次,并且无法用其再次创建对象,因为没有标签。

1.2 结构体的自引用

问题引入:一个结构体中是否能包含一个由自身创建的对象?

struct Person
{
	int age;
	struct Person relative;//创建一个亲戚对象
};

上述例子显然不对,可以巧妙地反证。

sizeof(struct Person)

假如成立,那么上述式子是无法计算出这个结构体的大小。

但是我偏要结构体中包含一个由自身所创建的对象,即结构体的自引用,那么该如何实现呢?

struct Person
{
	int age;
	struct Person* relative;
};

区别就在于,这个对象变成了结构体指针。
如若还不能理解,可以参照链表的相关知识进行深入理解。

如果再升一点难度,将结构体自引用与匿名结构体联系起来

typedef struct
{
	int data;
	Node* next;
}Node;

上述代码的意思是:首先创建一个匿名结构体,这个结构体包含一些成员,再为这个匿名结构体重定义,命名为Node。
但是这样写是错误的,因为对于一个结构体是先有成员后再有重定义的名字Node,所以其中的一个成员Node* next是非法的,Node还没有被重定义就被使用了。

解决方案

typedef struct Node
{
	int data;
	struct Node* next;
}Node;

1.3 结构体的内存对齐

问题引入:对于一个结构体,我们如何计算它所占空间的大小。

这个当中就涉及了近几年特别热门的知识点:结构体的内存对齐。

struct s1
{
	char c1;
	int i;
	char c2;
};

问:求这个结构体所占空间的大小?
利用画图软件进行内存分析:

在这里插入图片描述

问:为什么存在内存对齐呢?
答:内存对齐可以实现牺牲空间来换取时间利用效率。

1.4 修改默认对齐数

#pragma pack(8)

上述代码意思是设置默认对齐数为8,一般放置于结构体之前。

#pragma pack()

上述代码表示:取消设置的默认对齐数,还原为默认。
一般设置于结构体之后,与设置默认对齐数的代码共同使用。

1.5 结构体传参

传参分为传值和传址两种,传址更适合于结构体传参,因为可以避免因为结构体过大,参数压栈开销大(临时拷贝),所导致的性能降低。

二、位段

2.1 枯燥但不完全枯燥的基本概念

问:什么是位段?

  1. 位段的成员必须是整形家族。
  2. 位段的成员名后有冒号和数字,表示该成员所占比特位大小。
  3. 位段的形式和结构体十分相似,唯一的区别就是成员后面有冒号和数字。
struct A
{
	int a:2;
	int b:5;
	int c:10;
	int d:30;
}

需要注意的是:冒号后的数字16位机器最大16,32位机器最大32

2.2 位段的内存分配

问:上述的结构体A该如何在内存中分配空间呢?

答:位段的空间是按照成员数据类型来开辟的,如果是int就以4个字节,如果是char就以1个字节的方式来开辟的。
那么上述代码,都为int类型,那么先开辟4个字节,a、b、c三者加起来占17个bit,那么还剩15个bit,不够存放d的30个bit,那么这时候就直接舍掉这15个剩下的bit,再开辟4个字节用于存放d,所以这个位段的大小就是8个字节。

2.3 位段的优势与劣势

优势:可以节省空间。
比如用二进制表示性别时,只有三种可能:男、女、保密,那么就只用开辟两个bit位。

劣势:跨平台时可能出现不兼容的问题。
比如万一有的编译器偏要把开辟空间中剩余的比特位也利用起来,而不是舍去。

三、枚举

3.1 枚举的优点

enum Color
{
	RED,
	GREEN,
	BLUE
}

上述代码中RED默认值位0,如果不为其它枚举常量赋予初值的话,就依次往下递增1

问:能用#define定义常量,为什么要使用枚举?

答:好处一:可增加代码的可读性和可维护性。
比如在switch分支中,case所对应的选项可以运用枚举常量,而不是利用单纯的数字或者字符,利用有意义的单词可以让代码通俗易懂,同时也便于调试,还能一次性定义多个常量。
好处二:相较于#denfine定义的常量,枚举常量增加了类型检查

enum Color c = BLUE;
c = 2;//ok?

例如上述情况,第一行代码代表创建一个枚举对象,并为其赋值上BLUE(注意:枚举和结构体不同,枚举常量仅代表其创建的对象的可能取值),BLUE的值在上面的枚举中是2,所以给c赋值上2正确吗?

答:不正确。这样在cpp编译器下会出现类型不匹配的错误,提示为Color类型转换为了int类型。
而#define定义的常量不会出现这样的情况,所以不太利于程序的安全。

好处三:便于调试

在这里插入图片描述

好处四:相较于#define可以定义多个常量

四、联合(共用体)

4.1 基本概念

联合的声明举例

union Un
{
	char c;
	int i;
};

联合变量的定义

union Un un;

联合变量的大小计算

sizeof(un);//4

问题引出:联合变量是如何利用内存空间的?

答:联合的成员是共用一块内存空间的,比如上述例子中,c和i共用四个字节。
一个联合变量的大小,至少最大成员的大小。

printf("%p\n", &(un.i));
printf("%p\n", &(un.c));

由于这两个成员共用一块内存空间,所以它们所在的地址是相同的,那么上述代码的结果是相同的。

un.i = 0x11223344;
un.c = 0x55;
printf("%x\n", un.i);

上述代码又涉及到了内存的分布了,所以还是画个图来展示。

在这里插入图片描述

4.2 联合大小的计算

  1. 联合的大小至少是最大成员的大小。
  2. 当最大成员的大小不是最大对齐数的整数倍时,就要对齐到最大对齐数的整数倍。
union Un1
{
	char c[5];
	int i;
};
printf("%d\n", sizeof(union Un1)); 

上述代码的结果就应该是8,而不应该是5,因为最大对齐数是4,而5不是4的倍数。

  C++知识库 最新文章
【C++】友元、嵌套类、异常、RTTI、类型转换
通讯录的思路与实现(C语言)
C++PrimerPlus 第七章 函数-C++的编程模块(
Problem C: 算法9-9~9-12:平衡二叉树的基本
MSVC C++ UTF-8编程
C++进阶 多态原理
简单string类c++实现
我的年度总结
【C语言】以深厚地基筑伟岸高楼-基础篇(六
c语言常见错误合集
上一篇文章      下一篇文章      查看所有文章
加:2021-07-23 10:32:07  更:2021-07-23 10:32:14 
 
开发: 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年4日历 -2024/4/28 6:32:35-

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