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++知识库]自定义类型的很多精华

结构体类型

1 结构体类型的不完成声明

这种声明只能使用一次

了解就行

struct

{

char c;

int a;

}a,b;

struct

{

char c;

int a;

} *p;

&a == p;//编译器会报错,编译器会认为是两种类型,是非法的,所以最好别这样声明

最好别这样使用

2 结构体的初始化

使用大括号

要善于使用memset

typedef struct B

{

char name[20];

int age;

}b;

struct A

{

B stu;

char c;

int a;

}A;

b = {zhangsan,19};//单独初始化

A={{zhangsan,19},a,90}//结构题嵌套,那就在里面再加一个{},先初始化里面那个结构体

若里面嵌套的是一个结构体数组呢,那就不好初始化了呢

直接用前面提到的memset,如

struct A

{

B stu[20];

char c;

int a;

}C;

用memset初始化C

先看看这个函数memset如何使用吧(我们上cplusplus.com - The C++ Resources Network上面可查找函数使用)

ptr 传入要初始化数据的首地址,value要初始化的值,num初始化的大小

所以这里我们可以这样做

memset(&c, 0, sizeof(C));

这里就将sizeof(C)那么个字节大小的内存,每个内存都初始化为0;

如何求结构体类型的大小

先看看

struct P

{

char a;

int b;

double c;

}P;

P的大小是多少,先猜一猜,首先是不是觉得是1+4+8=13字节?恭喜你错了

首先,要知道内存对齐,这是求结构大小的关键方法

offsetof(),这是查数据的偏移量,知道偏移量,才能更好介绍内存对齐

#include

#include

struct P

{

char a;

int b;

double c;

}P;

int main()

{

printf("%d \n", offsetof(struct P,a));

printf("%d \n", offsetof(struct P,b));

printf("%d \n", offsetof(struct P,c));

return 0;

}

?

这就是结构体成员在内存中的放置位置,根据偏移量来放置

3 对齐数

对齐数是编译器默认的对齐数与该成员变量大小的较小值

当默认对齐数为4时,

char a; a 的大小是1字节,默认对齐数是4,那选一个较小值,那a的默认对齐数就是1

double c; c的大小是8字节,默认对齐数是4,那c默认对齐数是4;

?

VS默认对齐数是8

Linux下无默认对齐数

#pragam pack()可修改默认对齐数()里面修改的默认对齐数(一般改为2的n次方)

#pragam pack ()一般放在要修改的结构体定义之前

内存对齐的规则

1 结构体内的第一个成员放在结构体变量偏移量为0的地址处

?

2 第二个及之后的成员变量要放到它们自己的对齐数的整数倍处

b的对齐数是4,4是4的整数倍,且偏移量为4处未被占,那b就从偏移量为4处开始放

?

同样,c的偏移量为1,8是1的8倍,那就从8开始放入c。

?

3 结构体的总大小要为最大对齐数(成员和默认对齐数中最大的那个)的整数倍(含镶嵌结构体的对齐数)

看,结构体是从0偏移量数完,占9个字节,最大对齐数是4,那4的整数倍是12,那还要再拿出

3个空间来放着构成12个字节

所以这个结构体最终大小为12

?

来,去vs检测一下算的对不对

?

4 如果成员里结构体A包含结构体B(8字节),求A大小

如果镶嵌结构体B,B的当前对齐数(B中求出来的最大对齐数就是B的当前对齐数)和默认对齐数比,求出对齐数,方法和前三条一样

?

A的大小是多少呢?

首先,我们上次算出struct P大小位 12 byte,最大对齐数是4 ,

int b 大小是4,对齐数4

double c 大小是8,vs的默认对齐数是8,那它对齐数就是8;

然后画图来看

?

欧克,vs下检验一遍

?

如果结构体里面有个成员是数组,像char arr[20];

他的对齐数怎么求呢?

注意不是拿20比哈

他是char类型的,1字节,默认对齐数为8,那对齐数就是1,占12个字节

其他类型的以此类推

为什么要有内存对齐,内存对齐的作用

  1. 平台原因

不是所有硬件都能访问到任意地址处的任意数据,某些硬件只能在某些地址处访问到特定的某种类型的数据,否则可能硬件异常,所以为了硬件方便读取,存储对齐将特定类型的数据放在特定的位置处方便硬件读取

? ?2. 性能原因

数据结构(尤其是栈)应该尽可能的在自然边界上对齐。因为为了访问未对齐的内存,处理器需要作两次内存访问;而对齐的内存访问仅需要一次访问

如图

?

总之,结构体的内存对齐是以空间换取时间

在设计结构体的时候,尽可能的将大小差不多数据类型放一堆,集中在一起,节约空间

结构体传参

结构体传参时最好传地址,函数传参时,参数是会压栈的,会有时间与空间的开销,如果传的结构体对象过大,参数压栈的系统开销比较大,会导致性能下降,所以结构体传参时最好传地址

位段

1 .what is 位段 ?

位段就是在结构体数据成员名后面加一个冒号:and 一个数字;

哦,位段的成员只能是int ,unsigned int,singed int,char

Like this picture

?

2.how to calculate 位段大小?

其实最简单的也就是一个sizeof就算出来了,但是还是还是必须知道这个计算逻辑的

位段的空间是按照需求以4个字节(int)或者1个字节(char)开辟的,先开辟一次,用完或者不够再开辟一次

位段冒号: 后面那个数字是所需要的比特位

来复习一下,一个字节是多少比特位,忘了把我头打爆,说明好久没学了

8个哦

好,回来继续,看题

#define A 2
#define B 3
#define MAX_SIZE A+B
struct _Record_Struct
{
	unsigned char Env_Alarm_ID : 4;
	unsigned char Para1 : 2;
	unsigned char state;
	unsigned char avail : 1;
}*Env_Alarm_Record;
int main()
{
	struct _Record_Struct* pointer = (struct _Record_Struct*)malloc(sizeof(struct _Record_Struct) * MAX_SIZE);
	return 0;
}

字有点多,但全是精华。

malloc开辟了多大的空间;

首先,第一个是char 类型,先开辟一个字节,一个成员需要4个比特位,那还剩4个,第二个成员需要2个比特位

还剩下两个,第三个成员是结构体成员,需要一个字节,直接开辟,目前两个字节了

最后一个成员需要一个比特位,之前还剩两个比特位,但由于已经新开辟了一个字节

数据在内存中是按顺序放的,所以只能再开辟一个字节,占一个比特位,

还剩7个

总共开辟了三个字节,这个结构体占3字节sizeof(struct _Record_Struct)== 3,之后是预处理,直接

替换3*A+B ,最后算出来9字节,所以开辟了9个的大小空间

3.what's meaning for 位段?

首先,一定程度上节省空间,列如

struct A

{

int a:2; //

}

当a存储的数据数据状态只为:00,01,10,11

只需要两个比特位就能保存,但一个整型4字节,32比特位过于浪费,所以就可以用位段

像年龄,分数这样用位段就挺好

其次,数据的传输,用位段很好节省空间和时间

但是,位段有一定缺点 跨平台问题

1 int位段的数据被当成有符号数还是无符号数是不是确定的

2 位段在不同机器下的最大位的数目是不能确定的,在16位机器下一个int最大是16位,32位机器下最大位是32位

如果在冒号后写了个24这样的数,在32位机器下没问题,但到了16位机器就会处问题

3 位段成员在内存中的数据分配是从左到右,还是从右到左这是尚未定义的,不知的,取决于编译器,

注意!!!这不是大小端字节序,大小段是在以字节位单位情况下看的,既然这厮位段,位那就是比特位,所以与

大小端区分开

4 当一个结构包含两个位段时,第一个位段成员比较小,第二个比较大,当第一个成员使用一定内存后,还剩一定位,

再开辟新的位容纳第二个,之前的剩余的位是使用还是舍去,这是不确定的。

总之,与结构相比,位段可以达到同样的功能和效果时,位段可以很好节省空间,但是有跨平台的问题。

枚举类型

1.定义

这个东西应该算自产自销吧。。

列如

enum Sex

{

MALE,

FEMALE,

SECRET //最后一个枚举变量后面不打,

};//要有分号

枚举里面的内容是有一定值的,默认从0开始,一次增加1

?

枚举最开始可以在枚举体里面,给枚举变量赋初值的,之后出去就改不了

如:

?

2.枚举的优点

增加代码可读性和可维护性

与#define定义的标识符相比他是有类型的,更加严谨

便于携带调试,在预处理时,#define定义的标识符直接被替换了,调试时就已经换成对应的值了

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

联合体(共用体)

1.定义

这种自定义类型也包含一系列成员,这些成员共用一块空间

看看这个代码

?

联合体成员共用最大的那个空间,他在同一时间内只能用一个。

判断当前机器为是否大小段

用联合体来判断

int check_sys()

{

union Un

{

int i;

char c;

}u;

u.i = 1;

return u.c;

}

2.联合体大小的计算

联合体的大小至少是最大对齐数的整数倍

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

?

嗯,终于写完了,会尽快补齐之前到项目和笔记的,懒狗的泪,之前欠的以后总要还的,为了以后不还,只能现在还了

如果,哪位大佬看到发现错误,也请斧正,真的谢谢你!!!

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

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