C进阶 自定义类型

目录

前言

[一 结构体](#一 结构体)

[二 结构体的存储](#二 结构体的存储)

[三 位段](#三 位段)

[四 枚举](#四 枚举)

[五 联合体](#五 联合体)

总结


前言

我们之前学习的int char double ......都是内置类型,但是我们今天所学习的是自定义类型,比如联合体,结构体,枚举


一 结构体

结构体是一些值的集合,这些值统称为成员变量,每个成员都是可以用不同的的基本数据类型

结构体的使用场景:

结构体的意义在于可以进行封装一个整体的所有变量,这个是十分便捷的,这样就可以不用重复的操作进行重复的定义相同的东西,比如我们要统计一个班级的学生的学号,姓名,成绩,那么我们就可以使用结构变量,下面这个是使用结构体和不使用结构体的例子

cpp 复制代码
struct student {
	int number;
	char name[5];
	int score;
};
int main() {
	//不使用结构体
	int xiaomingnumber;
	char xiaomingname[5];
	int xiaomingscore;
	int xiaowangnumber;
	char xiaowangname[5];
	int xiaowangscore;
	//使用结构体
	struct student xiaoming, xiaowang;
}

结构体的基本形式:

cpp 复制代码
struct inflatable{
  char name[20]; 
  float volume; 
  double price;
};

结构体的匿名形式

cpp 复制代码
struct{
   int a;
   int b;
}x,b;

结构体需要注意的点
1 每个变量之间以分号隔开
2 最后要加上分号,因为这个是结构体的声明
3 匿名结构体只可以创建的时候定义变量

定义结构后,便可以创建这种类型的变量了

cpp 复制代码
struct inflatable hat;            // hat is a structure variable of type inflatable 
struct inflatable woopie_cushion; // type inflatable variable 
struct inflatable mainframe;      // type inflatable variable

由于 hat 的类型为 inflatable,因此可以使用成员运算符(.)来访问各个成员。例如, hat.volume 指的 是结构的volume 成员, hat.price 指的是 price 成员,当然在C++里面是可以把前面的struct省掉

初始化方式

cpp 复制代码
inflatable guest = {
  "Glorious Gloria", // name value 
  1 .88,             // vol ume value 
  29.99              // price value 
}

和数组一样,使用由逗号分隔值列表,并将这些值用花括号括起

结构数组

inflatable 结构包含一个数组 (name)。也可以创建元素为结构的数组,方法和创建基本类型数组完全相同。例如,要创建一个包含 100个inflatable 结构的数组,可以这样做:

cpp 复制代码
 inflatable gifts[100]; / / array of 100 inflatable structures

接下来的赋值操作也就是跟数组一样

结构中的位字段

创建与某个硬件设备上的寄存器对 应的数据结构非常方便。字段的类型应为整型或枚举(稍后将介绍),接下来是冒号,冒号后面是一个数字, 它指定了使用的位数。可以使用没有名称的字段来提供间距。每个成员都被称为位字段 (bit field)。下面 是一个例子:

cpp 复制代码
struct student {
    int number : 4;
    char xing  : 1;
    };

就是规定这个变量占用多少的字节,这个占用字节数是自己规定的

二 结构体的存储

结构体的对齐规则
1 第一个成员在与结构体变量的偏移量为0
2 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处
3 结构体的总大小为最大对齐数的整数倍

我们以下面这个结构体为例子来讲解

cpp 复制代码
struct  student{ 
    char c2;
    int number;
    char c1;
};

1 第一个成员在与结构体变量的偏移量为0

这个就是这个变量i前面没有偏移量直接占用0这个各自

2 其他成员变量要对齐到某个数字(对齐数)的整数倍的地址处

我们以其他的变量来讲解这个东西

我们可以看到这个空白的,这个就是偏移量,然后偏移到(对齐数)的整数倍,一般都是4,然后我们就可以得到这个是8了

3 结构体的总大小为最大对齐数的整数倍

我们最后到了这一步之后就是4的整数倍,里面最大的对齐数为4,所以为8

为什么会有对齐原则

1 平台原因

不是所有的硬件平台都可以任意的访问任意地址的数据的,某些平台只可以在某些地址处去某些特定的数字,否则会抛出异常

2 性能原因

1 在现在的CPU里面,访问内存是按照快的标准执行的,一个典型的块的大小为4字节,8字节甚至更大,这与CPU的数据总线宽度有关,32位通常是4字节,64通常是8字节

2 数据总线宽度
CPU一次性传输可以处理多少的数据的字节数
宽度越大,CPU每次处理的数据量就越大
32位数据总线宽度意味着32条并行通道,这样CPU一个时间周期可传输32位数据

由于CPU是以快为主,所以就会牺牲空间提高性能

三 位段

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

1,成员必须为整形家族的 2,位段的成员后面都带有一个冒号和数字

cpp 复制代码
struct A{
    int a: 2;
    int b: 3;
    int c: 4;
    int d: 5;
};

这个就是说a占用2个字节 b占用3个字节 c占用4个字节 d占用5个字节,运用这个就是压榨内存,因为内存是一个非常昂贵的资源

内存分配

原则

1 位段的成员都是整形家族

2 空间按照需以4字节或者1字节的方式来开辟

3 位段涉及很多不确定因素,位段考虑跨平台和可移植性应避免使用位段

以上面为例子:2+3+4+5=14,但是真的是这样吗?

首先线开出1字节,看够不够用,不够用就再开辟一个字节,继续存储,中间那个空白的就是浪费的

所以他的分配方式就是:不断地开辟一字节,看是否够用,不够的话就再继续开辟,直到所有的都满就好

位段在跨平台编程中存在诸多问题,主要体现在以下几个方面:

1. 位段的符号性不确定

  • int 类型的位段在某些平台上可能被解释为有符号数,而在另一些平台上可能被解释为无符号数。

2. 位段的最大位数不确定

  • 不同平台的位段最大位数可能不同。例如,16位机器上最大为16位,32位机器上最大为32位。如果定义的位数超过目标平台的最大限制,会导致编译错误。

3. 内存分配顺序不确定

  • 位段成员在内存中的分配顺序(从左到右还是从右到左)在标准中未明确定义,不同编译器可能有不同的实现。

4. 位段的存储布局不确定

  • 当一个位段的剩余空间不足以容纳下一个位段时,编译器可能会选择丢弃剩余空间或利用剩余空间,这种行为在不同平台上是不确定的。

5. 编译器差异

  • 不同编译器对位段的实现和优化方式可能不同,这也会导致跨平台时的行为差异。

四 枚举

cpp 复制代码
enum sex{
  MALE;
  FEMALE;
  SECRTX;};

作用:是提高代码的可读性和在进行项目编写的时候,提高规范性

计算机会根据你的放置进行推算,但是是从0开始

如上述就是MALE为0......

枚举里面输入数字的话会更加的清晰

五 联合体

联合体的格式

cpp 复制代码
uion un{
   int a;
   char i;
};

联合体就是一起公用一个空间,最妙的放法就是用a不用i,用i不用a,一定程度地减少空间地消耗

联合体地大小

1 联合体的大小为成员里面最大类型的大小

2 当最大成员不是最大对齐树的整数倍的时候,就要对齐到最大成员的整数倍数

我们来举个例子

cpp 复制代码
union Un{
   char arr[5];
   int a;
};

5和4字节放到了一起,但是要对齐到最大对齐数的整数倍数,我们就开到了8

剩下的空白是不用的,开辟不用

char arr[5]和5个char类型的变量是不一样的

第一个是开辟了5个,第二个是开辟了1个,共用一个


总结

结构体

初始化,定义,存储

位段

初始化,定义存储

枚举

定义,用处

联合体

定义存储

相关推荐
go54631584651 小时前
本地部署 GitHub 上的 Python 人脸识别项目
开发语言·python·github
USER_A0012 小时前
【C语言】第八期——指针、二维数组与字符串
c语言
wjs20242 小时前
PHP 连接 Memcached 服务
开发语言
溟洵3 小时前
【C/C++】理解C++内存与Linux虚拟地址空间的关系---带你通透C++中所有数据
linux·c语言·c++
Chandler244 小时前
C++11 智能指针:unique_ptr、shared_ptr和weak_ptr 功能特性 模拟实现
开发语言·c++
十八朵郁金香4 小时前
深入理解 JavaScript 中的 this 指向
开发语言·前端·javascript
让学习成为一种生活方式4 小时前
libGL.so.1: cannot open shared object file: No such file or directory-linux022
linux·开发语言·python
贵州晓智信息科技4 小时前
使用 Three.js 转换 GLSL 粒子效果着色器
开发语言·javascript·着色器
一只蜗牛儿5 小时前
C# 版 OpenCV:OpenCVSharp 最详细最全面教程(万字详细总结)
开发语言·opencv·c#