C语言 数据存储之结构类型 万字讲解#数据类型详细介绍 #整型在内存中的存储 #大小端字节序 #浮点型在内存的存储解析

文章目录

目录

前言

一、数据类型详细介绍

类型的意义:

 1、类型的基本归类

a.整型家族

b.浮点型家族

c.构造类型

数组类型

结构体类型  struct 

枚举类型  enum

联合类型  union

d.指针类型

e.空类型

二、整型在内存中的存储

三、大小端字节序

什么是大端字节序、小端字节序?

为什么会有大小端字节序?

练习题:设计一个程序来判断一个当前机器的字节序

例1:(输出什么?)

例2:(输出什么?)

四、浮点型在内存的存储解析

1、十进制 - 二进制 - 科学计数法

2、对将M、E存入内存中的规定:

3、浮点数的读取:

1、E不全为0或者不全为1

2、当E全为0时

3、当E全为1时

总结


前言

万字讲解

赶紧收藏起来!


一、数据类型详细介绍

在前面我们已经学过很多的内置类型:

char  //字符数据类型   1 byte 

short  //短整型数据     2 byte

int   //整型       4 byte

long  //长整型      4byte (32位 )\  8 byte (64位)

long long  //更长的整型    8 byte

float  //单精度浮点数   4 byte 

double  //双精度浮点数     8 byte

类型的意义:

1、使用这个类型所开辟内存空间的大小(大小决定了使用范围)

2、如何看待内存空间大小的视角

分析,类型决定了所开辟内存空间的大小;即,若我创建一个char 类型的变量,那么它向内存申请 1 byte 的空间来存储数据;若我创建一个short 类型的变量,那么它向内存申请了 2 byte 的空间来存储数据……而如何看待内存空间的大小的视角呢?例如:int a = 1; --> 变量a 的类型是int ,站在a 的视角便认为a 里面放的 1 是整型数据 ; float b = 1.0f ; --> 变量b 的类型是float ,站在b的视角便认为 b里面放的是 1.0 是浮点型类型;

即使a、b 在内存中所占的空间为 4byte ,但是由于a、b 的类型不同它们的立场也不同,所以它们看这 4 byte 中的内容数据便有所差异;

 1、类型的基本归类

a.整型家族

char (默认可能是 unsigned char,也有可能是 signed int ;取决于编译器)

            unsigned char

            signed char 

注:字符在内存中本质上存的是ASCII码值,故而char 类型属于整型家族;

short (默认是 signed short (int))

            unsigned short  (int)

            signed short (int) 

int   (默认是 signed int )

             unsigned int

             signed int

long  (默认是 signed long (int))

            unsigned long (int)

            signed long (int)

long long (默认是 signed long long (int) )

            unsigned long long (int)

            signed long long (int)

注:long long 是C99 标准引入的类型

思考: signed 与 unsigned 到底有什么用?它们二者之间有什么区别?

生活中年龄、身高等数据等是没有负数的;故而signed 类型的数据表示有正数有负数,但unsigned类型的数据不表示负数;数据在内存中存储的是二进制的补码,而signed 类型的数据的最高位为符号位代表着这个数据是正还是负;而unsigned 即无符号类型,也就是说这些数据在内存中存的二进制的补码中的最高位不为符号位而是有效位;以char 类型为例子,那么显然signed 类型的数据可存放在内存中只有7bit 位,即signed char 可表示范围为 [-128,127] ; 而unsigned char 中在内存中的补码的最高位的不为符号位,所以便有8 bit位来存放数据,即 unsigned char 可表示的范围为 [0,255];

b.浮点型家族

浮点型家族:只要是表示小数就可以使用浮点型;float 的精度低,存储的数据范围较小;double 的精度高,存储的类型的范围更大。

float

double

c.构造类型

构造类型即自定义类型(即我们可以自己创建的类型)

数组类型

数组的类型:去掉数组名剩余的便为数组的类型;只要数组元素的类型与个数在发生变化,数组的类型就在发生变化,故而数组类型是构造类型;

结构体类型  struct 
枚举类型  enum
联合类型  union

d.指针类型

指针类型即通过创建指针变量

int* p1;

float* p2;

void* p3;

e.空类型

空类型即无类型

void 表示空类型,void 通常运用于函数类型的返回值、函数的参数、指针类型

当void 应用于函数类型的返回值,以表示此函数不用返回任何东西;

当void 应用于函数的参数时,即代表在这个函数明确不需要给此函数传参,即此函数不需要参数;但是当void 应用于函数的参数时,仅仅只是是说这个函数不需要参数,但如果你硬要是传参给这个函数,它也没有办法只有看着你,不过此函数仍然不会使用此参数;

当void 用来表示指针类型的时候,例如:void* p; 即创建了一个void* 类型的指针变量 p;

二、整型在内存中的存储

通过前文我们可知,当一个变量创建的时候便会根据此变量的类型向内存申请空间来存放数据,空间的大小是根据不同的类型决定的;

那么数据在开辟空间的时候到底是怎样存储的呢?

例如:

int a = 20;

int b = -10;

我们知道变量 a、 b 的类型为 int 类型,在创建的时候回向内存空间申请 4byte 大小的空间来存储数据,那么这些数据是怎样的形式存储在空间中呢?可以看此详细讲解的文章:链接在此:http://t.csdnimg.cn/DiyC2

数据可以有很多种表示形式即二进制、八进制、十进制、十六进制等;然而当整数以二进制的形式来表示的时候,又会有三种表现形式:原码、反码、补码;

注:1、正整数的原码、反码、补码相同

2、负整数原码、反码、补码需要计算才能得到;

原码、反码、补码均有符号位和数值位两部分,符号位即即二进制序列最左边的一位,用0来表示正数;用 1 来表示负数;

原码:根据此数值的正负直接写出来的二进制序列

反码:在原码的基础上,符号位不变,其他位按位取反

补码:在反码的基础上+1

根据以上例子:int a = 20; int b = -10; 

变量a 的原码、反码、补码:00000000 00000000 00000000 00010100

变量b 的原码:10000000 00000000 00000000 00001010

                        十六进制表现形式:0x1000000a

              反码:11111111 11111111 11111111 11110101

                         十六进制表现形式:0xfffffff5

              补码:11111111 11111111 11111111 11110110

                         十六进制表现形式: 0xfffffff6

注:想要详细了解负整数原码、反码、补码的计算过程看此链接:http://t.csdnimg.cn/DiyC2

调试之后观察变量b 的地址,便可以得知数据在内存中存储的是原码还是反码或者是补码;

此处 &b 之后我们发现,在内存窗口中(这里是调试小技巧,想要了解可以点此来链接:http://t.csdnimg.cn/JDy0E);地址实际上是二进制序列,为了方便查看,呈现的时候我们看到的是十六进制(博主用的是x64 位) ;同理,在内存中存放的数据也是如此,本质上存的是二进制序列,但是为了便于查看,是以十六进制呈现的;从上图,我们可以得知,变量b 在内存中存储的是 0xfffffff6,即变量b 补码的十六进制数据,

故而数据在内存中存放的是二进制序列的补码;

为什么在内存中存放的是补码呢?

1、使用补码可以将符号位和数值位统一处理

2、加法和减法可以统一处理(CPU只有加法器)

3、补码与原码的相互转换,其运算过程是相同的,故而不需要额外的硬件电路;

注: 负整数中,将原码转换成补码:在原码的基础上符号位不变,其他位按位取反,得到反码,再在反码的基础上+1

那么将补码转换成原码?显然将原码转换成补码的步骤反过来就行了,即在补码的基础上-1得到反码,而在反码的基础上符号位不变其他位按位取反得到了原码; 然而实际上,将补码转换成原码也可以这样:在补码的基础上符号位不变其他位按位取反,得到反码,然后在反码的基础上+1,便得到了原码;

我们来看一下图解:(还是以 int b = -10 为例子)

方法一:

方法二:

三、大小端字节序

例子: int b = -10;

下图为在x64环境下调试后 &b 的内存窗口:

我们先来梳理一下原理:内存单元的大小为 1 byte, 而 1 byte = 8 bit 也就是说可以存放 8个二进制位,一个十六进制位相当于四个二进制位;故而 1 byte 存放了两个十六进制位;所以0x00000014B076F884 这个地址(内存单元)中存放的是 f6 ,0x00000014B076F885 这个地址中存放的是 ff ;0x00000014B076F886 这个地址中存放的是 ff ; 0x00000014B076F887 这个地址中存放的是 ff ;但是变量b 实际在内存中补码的十六进制表示是0xfffffff6,想必你提出一个疑问:数据是倒着存放的?为什么呢?

内存是一块连续的空间,由于每个内存单元的大小为1byte,当一个数据所占内存空间的大小大于 1 byte 的时候,就会有个”小尾巴“,这个”小尾巴“到底是向左摆呢还是向右摆(在这里将内存看作了横向的连续空间),就会存在一个顺序问题,即大小端字节序;

大小端的概念来源于《格列佛游记》中一个吃鸡蛋的问题,即一个吃鸡蛋到底是从鸡蛋的小端开始吃还是从鸡蛋的大端开始吃;同理,”大小端字节序“中的”大小端“可以理解为数据在内存中排列顺序的问题,而”字节序“则是由于内存单元的大小为 1byte,当数据大于 1byte 的时候,就存在每一个大小为1字节数据之间顺序问题(以字节为单位讨论数据在内存中的存储顺序);

为什么只有大端、小端这两种顺序呢?不是说只要怎么存放都可以,只要当数据使用的时候,我按照原理展开就行了吗?理论上是可行的,但是如果存放规则没有定下来而去解决于怎么存(非大端和小端的方法)就怎么取,各种各样的方式就非常复杂,太麻烦了,于是乎后来就渐渐地变得之后大端和小端这两种数在内存中存放的顺序;

什么是大端字节序、小端字节序?

当数据顺着地址由低到高的顺序存放进去就为大端字节序,即把一个数据的高位字节序放在低地址,而其低位字节序放在高地址。

当数据逆着地址由低到高的顺序存放进去就为小端字节序,即把一个数据的高位字节序放在高地址,而其低位字节序放在低地址;

为什么会有大小端字节序?

这是因为在计算机系统中,内存被分为一个个内存单元,而一个内存单元的大小为1byte,一个字节为8比特位,但是在C语言除了8bit 的char 类型以外,还有18 bit 的short 类型、32 bit 的long 类型(要具体看其编译器),且在位数大于8 位的处理器,例如 16位、32位的处理器,由于寄存器的宽度大于一个字节,那么就必然存在多个字节安排的问题;即内存是一块连续的空间,由于每个内存单元的大小为1byte,当一个数据所占内存空间的大小大于 1 byte 的时候,就会有个”小尾巴“,这个”小尾巴“到底是向左摆呢还是向右摆(在这里将内存看作了横向的连续空间),就会存在一个顺序问题;因此就导致了大端存储模式和小端存储模式;

注:只要是在内存中申请的空间大于 1 byte 的类型,都存在大小端字节序的问题;

练习题:设计一个程序来判断一个当前机器的字节序

代码如下:

#include<stdio.h>int is_check_says()
{int a = 1;return *(char*)&a;
}int main()
{int ret = is_check_says();if (ret)printf("小端\n");elseprintf("大端\n");return 0;
}

分析:封装成一个函数专门来判断当前机器是大端还是小端;用 Int a = 1;就非常巧妙;变量a 补码的十六进制的写法:0x00000001; 如果当前机器是大端字节序那么此数据在内存中存储的顺序就是:00 00 00 01;而若是小端字节序,那么此数据在内存中存储的顺序就是 01 00 00 00 ; &a ,取出的地址是变量a 存储在内存空间中4字节中第一个字节的地址,由于变量 a的类型为Int 类型,所以变量a地址的类型为int* ,若是相对此地址进行解引用,因int* 的权限为 4字节,所以会访问变量a 存放在内存中4字节的数据;而这里想要区分大小端字节序只需要访问变量a 存放在内存中4个字节中第一个字节的内容,故而应该先对变量a 的地址进行强制类型转换而后再解引用;所以需要这样写:* ( char* ) &a ; 若是当变量a 存储在内存中的数据为1 的时候,取其第一个字节的内容,如果是1 ,则说明是小端字节序;如果是0,则说明是大端字节序;

例1:(输出什么?)

代码如下:

#include<stdio.h>int main()
{char a = -1;signed char b = -1;unsigned char c = -1;printf("a=%d,b=%d,c=%d\n", a, b, c);return 0;
}

代码运行结果如下:

分析:在vs中,char 类型默认为 signed char 类型,signed char 类型的取值范围为[-128,127]; -1是整型,为32bit,其反码为:11111111 11111111 11111111 11111111 ,而 signed char 在内存空间中占1 byte即8 bit , 所以将-1存入 signed char 会发生截断,即signed char在内存空间存放的是 11111111;在printf() 函数中占位符 %d 的对象是有符号整型,所以此处会发生整型提升,有符号的的整型提升,高位补的是其符号位,即 :11111111 11111111 11111111 11111111,符号位是1代表此数为负数,而负整数的原码、反码、补码需要计算才能得到;经计算得其原码为 :10000000 00000000 00000000 00000001 , 所以 a = -1; b = -1 ;

而unsigned int 类型的取值范围为 [0,255];故而unsigned char不能用来表示负数;-1是整型,为32bit,其反码为:11111111 11111111 11111111 11111111 ,而 unsined char 在内存空间中占1 byte即8 bit , 所以将-1存入 unsined char 会发生截断,即unsigned char在内存空间存放的是 11111111;由于%d 打印的有符号整型,变量c 的类型为unsigned char ,便会发生整型提升;无符号整型的提升直接在高位补0,即00000000 00000000 00000000 11111111,符号位为0说明该数为正整数,正整数的原码、反码、补码相等;所以 c = 255 ;

例2:(输出什么?)

代码如下:

#include<stdio.h>int main()
{char a = -128;printf("%u\n", a);return 0;
}

代码运行结果如下:

分析:在vs编译器中 char 默认为 signed char 类型,其值的表示范围为 [-128 , 127];但是 printf() 函数中的占位符是 %u,来打印无符号整型的占位符;

-128为整型,其补码: 11111111 11111111 11111111 1000000,存放到 类型为 signed char 类型的变量a 中,便会发生截断即 1000000 ;由于%u是用来打印无符号整型的占位符,故而此处会发生整型提升,有符号的整型提升高位补其符号位,即得到补码:11111111 11111111 11111111 1000000,但是无符号整型无符号位则说明该值位正整数,即此32为均为有限位,即11111111 11111111 11111111 1000000 的十进制值为:4294967168

四、浮点型在内存的存储解析

1、十进制 - 二进制 - 科学计数法

根据IEEE(电气和电子工程协会)754,任意一个二进制浮点数V可以表达成下面的形式:

即 V = ( -1 )^ S * M * 2^E

(-1)^S 为符号位,当S为0时,V为整数;当S为1时,V为负数;

M表示有效数字,[ 1, 2)

2^E 表示指数位;

接下来,我将以举例子的形式来让你理解这个式子: V=( -1 )^S * M * 2^E;

例3:

V = 5.5f;  

此处的 5.5为浮点数,f 表示它的类型为float 类型;

5.5 为十进制的表示形式,怎么用二进制来表示呢? --> 小数点前二进制+小数点后二进制,即其二进制写作:101.1 (请注意:看其权重)--> 写成科学计数法:1.011 * 2 ^ 2 (可自行类比十进制数的科学计数法),那么此浮点数的二进制序列便可以写成 : V = ( -1 )^0 * 1.011 * 2^2 ,其中 S = 0 , M = 1.011 , E = 2  ;

但是用二进制序列存储浮点数,由于是用权重,可能就会出现有些浮点数无法被精确存储,或者即使可以精确存储但是由于位数太多(总位数大于32位或者64位,即float 类型与 double 类型)也会导致存储不精确的问题。这也就是浮点数为什么可能会存在存储不精确的原因

由于任意一个浮点数均可以用 V = ( -1 )^S * M * 2^E 来表示,那么只要将S,M,E这三个数据信息存储在内存中即可,等到要使用该浮点数的时候,计算机再将这三个数据解读便可以了;

2、对将M、E存入内存中的规定:

有效数M属于[ 1 , 2) ,M总是大于1,故而将其存入内存的时候便不存第一位的1,在读取的时候加上就行了;这样做便可以多一个比特位来存储数据。而指数位 2^E (按理说科学计数法可以向左移、向右移,故而E有正有负),但是E的类型为 unsigned int ,如何解决这个问题呢?--> IEEE754规定存入的E的真实值需要加上其取值范围的中间值;当此浮点数为float 类型时,E 占8bit ,取值范围为 [0 , 255] --> 中间值为127 ; 当此浮点数类型为double 类型时,E占11 bit, 取值范围为 [0 , 2027] --> 中间值为 1023;

对于float 类型的浮点数,有32比特位,S占了1bit 位,E 占了8bit 位,M占了 23bit 位;

eg.V=0.5;为float 类型的数存入内存中:(S+E+M)

0 01111110 00000000000000000000000

注:内存中存储M时绿色的0是补的,由于M存储的时候没有存第一位的1,所以在解读的时候计算机便会加上,故而0补在后面;

对于double 类型的浮点数,有64比特位,S占了1bit 位,E 占了11bit 位,M占了 52bit 位;

eg.V=0.5;为double 类型的数存入内存中:(S+E+M)

0 00001111110 0000000000000000000000000000000000000000000000000000

注:内存中存储M时绿色的0是补的,由于M存储的时候没有存第一位的1,所以在解读的时候计算机便会加上,故而0补在后面;

3、浮点数的读取:

指数E从内存中有三种情况:

1、E不全为0或者不全为1

此时,浮点数就采用以下规则表示,即指数E的计算值(E存储在内存中的数值)减去127(或1023),得到真实值,再将有效值M前加上第一位的1;

eg.还是以float类型的0.5为例;

其补码为: 0 01111110 00000000000000000000000

S = 0; E = 01111110 ; M=00000000000000000000000;真实值:S = 0 ; E = 126 - 127 = -1 ; M= 1.0 --> ( -1 )^0 * 1.0 * 2^( -1 ) ;算出来也是0.5 ;

2、当E全为0时

规则:浮点数的指数等于 1-127 (或者 1-1023)即为真实值,有效数字M不再加上第一位,而是还原成0.xxxxxxxxx的小数。这样做是为了表示+\- 0,以及接近于0很小的数值。

2^E 为指数位,当存入内存中的E全为0时,当浮点数位float类型即为32bit时,则E的真实值 =1-中间值127 ,代表着E真实值为-126,那么2^E 算出来的结果就非常小,无限接近于0;浮点数为double类型时同理;

3、当E全为1时

规则:此时,如果有效数字M全为0,表示+\- 无穷大(正负号决定于符号位S)

2^E 为指数位,当存入内存中的E全为1时,当浮点数位float类型即为32bit时,则E的真实值 =内存中存放的 (255)- 中间值(127),即代表着E真实值为128,那么2^E 算出来的结果就非常大;浮点数为double类型时同理;

例3:(浮点数存储)

代码如下:

#include<stdio.h>int main()
{int a = 9;float* p = (float*)&a;printf("a=%d\n", a);printf("*p=%f\n", *p);*p = 9.0;printf("a=%d\n", a);printf("*p=%f\n", *p);return 0;
}

代码运行结果如下:

分析:变量a 的类型为int 类型,故而其地址为 int* 类型,所以若想要将变量a 的地址存入float* 类型的指针变量p 中,便要将&a 进行强制类型转换,所以得到 float* p = (float*)&a; 而printf() 函数中的占位符 %d 表示打印整型数据,变量a 的类型为int 类型,所以 printf("a=%d\n", a); 的输出为 9; 而printf() 函数的占位符 %f 表示打印浮点型float 类型的数据,也就是说时按照float 类型的读取方式来读取内存中的补码;变量a 在内存中的存储的二进制序列( 补码 ) :00000000 00000000 00000000 00001001 ;以浮点数的方式进行读取,即S=0; E= 00000000 ;    M=0000000 00000000 00001001; 此时E为全0,所以E的真实值=1-127=-126,而M=0.0000000 00000000 00001001;,表示一个很小的值,无限接近于0;即 (-1)^0 * 2^(-126) * 0.0000000 00000000 00001001 ,故而输出为 0.000000.

*p = 0; 就是对指针p 指向的对象赋值为 浮点型9.0,即此处是以 float 类型存入变量a 所处的内存空间之中;9.0的二进制 --> 1001.0 --> 科学计数法:1.0010 * 2^ 3 --> (-1)^0 ^ 1.0010 *  2^ 3 ;则S=0;E=3;M=1.0010;存入内存当中,S占 1bit ,E占8bit ,E存入内存中的值=真实值+中间值(127) = 130;M占23 bit,存入内存中不存入第一位的1 ,即存入0010,位不够便在其后补0;所以变量a存入内存中的二进制序列为:0 10000010 00100000000000000000000 ; 而printf() 函数中的占位符 %d 打印的是整型数据,所以读取内存中的数据是以整型的读取方式来读取的,因符号位为0代表着此数为正整数,正整数的原码、反码、补码相同;二进制序列:0 10000010 00100000000000000000000的十进制表示形式为:1091567616所以printf("a=%d\n", a);的输出结果为:1091567616

而 printf() 函数的占位符为 %f 打印的是浮点型类型,所以读取内存的方式是以浮点型的读取方式来读取的;即存入内存中的S=0;E=10000010;M=00100000000000000000000; ,而打印出来 S=0; E的真实值为= 内存中的数值 - 中间值(127)=3 ; 在读取M的时候加上1,即M=1.00100000000000000000000;   -->   ( -1)^0 * 1.00100000000000000000000 *2^3  -- > 1001.00000000000000000000 --> 十进制:9.00000000000000000000,由于float 类型--> 9.000000;


总结

1、类型的意义:使用这个类型所开辟内存空间的大小(大小决定了使用范围);如何看待内存空间大小的视角

2、类型的基本归类:整型家族;浮点型家族;构造类型:数组类型、结构体类型、枚举类型、来联合类型。指针类型;空类型;

3、大端字节序当数据顺着地址由低到高的顺序存放进去就为大端字节序,即把一个数据的高位字节序放在低地址,而其低位字节序放在高地址。

小端字节序:当数据逆着地址由低到高的顺序存放进去就为小端字节序,即把一个数据的高位字节序放在高地址,而其低位字节序放在低地址;

4、二进制浮点数V可以表达成下面的形式: V = ( -1 )^ S * M * 2^E

(-1)^S 为符号位,当S为0时,V为整数;当S为1时,V为负数;

M表示有效数字,[ 1, 2)

2^E 表示指数位;

5、对将M、E存入内存中的规定;

6、浮点数的读取:

E不全为0或者不全为1:此时,浮点数就采用以下规则表示,即指数E的计算值(E存储在内存中的数值)减去127(或1023),得到真实值,再将有效值M前加上第一位的1;

当E全为0时,规则:浮点数的指数等于 1-127 (或者 1-1023)即为真实值,有效数字M不再加上第一位,而是还原成0.xxxxxxxxx的小数。这样做是为了表示+\- 0,以及接近于0很小的数值。

当E全为1时,规则:此时,如果有效数字M全为0,表示+\- 无穷大(正负号决定于符号位S);

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/49714.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

MySql性能调优05-[sql实战演练]

sql实战演练 行列转换行列式转换第一题【列转行】第二题【列转行】 having的使用找到表中&#xff0c;名字重复的项有数据表employee&#xff0c;包含如下字段id、name、department、age&#xff0c;编写SQL&#xff0c;找到不与其他人同龄的年纪最大的员工的年龄有数据表emplo…

使用LibTorch加载预训练PyTorch模型实践

PyTorch如今发布到1.1稳定版本&#xff0c;新增的功能让模型部署变得更为地简单&#xff0c;本文记录如何利用C来调用PyTorch训练好的模型&#xff0c;其实也是利用官方强大的LibTorch库。 LibTorch的安装 虽然说安装&#xff0c;其实就是下载官方的LibTorch包而已&#xff0…

ModelArts中sinh算子的开发

一、环境配置 1、创建notebook并连接 使用ModelArts新建一个notebook,我这里镜像选择第一个,里面含有cann和Ascend910处理器,我这里环境只能使用ssh连接,创建一个密钥对,保存到C盘中的user/Administrator/目录下。 在网页中选择使用vscode接入,等待vscode打开后,选择密…

对链表的头结点和各个指向结点的引用的理解。力扣24题,两两交换链表中的结点。

头结点 其实是知道在链表前面添加一个没有实际存储内容的头结点是有利于程序运行的&#xff0c;但是在实际编程中总是会忘记或者不知道到底起到什么样的作用&#xff0c;或许这就是纸上得来终觉浅&#xff0c;绝知此事要躬行吧。 力扣24题要求我们两两交换链表中的结点。题目…

PotatoTool 蓝队版 V1.3 发布:增强功能和性能优化

一、简介 经过广大网友的反馈和建议&#xff0c;我们对V1.1版本中存在的问题进行了优化。其中&#xff0c;我们针对MD5库进行了本地化处理&#xff0c;以提高查询效率。然而&#xff0c;这也导致了软件体积的飙升。二、优化概述 1、兼容性 兼容arm架构系统 2、UI 2.1 界面…

Linux磁盘扩容lvm

目录 Linux磁盘管理基础知识介绍 1.确认分区类型 2.添加新硬盘 3.给新硬盘添加分区 &#xff08;2&#xff09;指定分区类型 4.创建物理卷 5.创建卷组 6.扩展逻辑卷 7.刷新文件系统 &#xff08;1&#xff09;查看文件系统 xfs文件系统使用&#xff08;centos&#…

【YOLOv8系列】图像分类篇----通过YOLOv8实现图像分类功能

最近需要使用YOLOv8对自己的数据集进行训练,从而实现图像分类的功能,因此记录一下整个过程。 YOLOv8的github地址:https://github.com/ultralytics/ultralytics 参考链接:超详细YOLOv8图像分类全程概述:环境、训练、验证与预测详解 文章目录 一、YOLOv8环境搭建二、准备…

80. 删除有序数组中的重复项 II【 力扣(LeetCode) 】

一、题目描述 给你一个有序数组 nums &#xff0c;请你 原地 删除重复出现的元素&#xff0c;使得出现次数超过两次的元素只出现两次 &#xff0c;返回删除后数组的新长度。 不要使用额外的数组空间&#xff0c;你必须在 原地 修改输入数组 并在使用 O(1) 额外空间的条件下完成…

docker部署mysql8.x版本,shell脚本字段部署安装mysql

docker部署mysql8.x版本&#xff0c;shell脚本字段部署安装mysql **1.**先自行安装好docker环境&#xff0c;docker的镜像注册中心最好是国内的&#xff0c;例如执行一下命令直接修改docker配置&#xff0c; cat <<EOF > /etc/docker/daemon.json {"registry-m…

深入理解算数表达式求值:后缀表达式的转换与计算

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;没人会嘲笑竭尽全力的人&#xff01; 前…

python实现定时任务功能的两种方案

第一种方式&#xff0c;使用python自带的threading库&#xff0c;使用递归调用实现定时任务 import threading import time def job():print("定时任务执行")# 设置定时任务的间隔时间&#xff0c;单位为秒interval 5# 使用递归调用实现定时任务的循环执行threadin…

PT2262-IR

PT2262是一款很古老的编码芯片&#xff0c;其兼容型号有&#xff1a;SC2262&#xff0c;AD2262&#xff0c;SC2260(需改变匹配电阻)等。 依据其datasheet&#xff0c;PT2262射频模式工作原理: CODE BITS A Code Bit is the basic component of the encoded waveform, and ca…

34_YOLOv5网络详解

1.1 简介 YOLOV5是YOLO&#xff08;You Only Look Once&#xff09;系列目标检测模型的一个重要版本&#xff0c;由 Ultralytics 公司的Glenn Jocher开发并维护。YOLO系列以其快速、准确的目标检测能力而闻名&#xff0c;尤其适合实时应用。YOLOV5在保持高效的同时&#xff0c…

13、.Net相关的书籍 - .Net循序渐进系列文章

这篇博文介绍.Net相关的书籍。 1、 ASP.NET。 ASP.NET作为微软.NET体系里的重要组成部分&#xff0c;得到了微软合作伙伴以及众多的微软编程爱好者的欢迎。ASP.NET在经历了好几个版本的更新之后&#xff0c;其内容也越来越充实了。目前ASP.NET的版本是4.0版&#xff0c;其中…

LeetCode/NowCoder-二叉树OJ练习

励志冰檗&#xff1a;形容在清苦的生活环境中激励自己的意志。&#x1f493;&#x1f493;&#x1f493; 目录 说在前面 题目一&#xff1a;单值二叉树 题目二&#xff1a;相同的树 题目三&#xff1a;对称二叉树 题目四&#xff1a;二叉树的前序遍历 题目五&#xff1a;另…

【ifconfig 命令用于查看的网络接口信息说明】

ifconfig 命令用于查看的网络接口信息说明 提示:本文是在Ubuntu系统上测试 网络接口信息 6:~$ ifconfig en2s0f0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether f8:e2:1e:63:19:61 txqueuelen 1000 (以太网) RX packets 100 bytes 1000 (0.0 B) RX errors 1 d…

C++ 访问修饰符 private、protected、public

C 访问修饰符 private&#xff0c;protected&#xff0c;和public flyfish 2009-01-19 2024-07-23 做成表格形式&#xff0c;可以直接拖到下面&#xff0c;看表格形式更清楚。 访问修饰符&#xff08;Access Modifiers&#xff09;是C中用于控制类和结构体成员&#xff08;包…

鸿蒙OpenHarmony Native API【drawing_path.h】 头文件

drawing_path.h Overview Related Modules: [Drawing] Description: 文件中定义了与自定义路径相关的功能函数 Since: 8 Version: 1.0 Summary Functions FunctionDescription[OH_Drawing_PathCreate] (void)[OH_Drawing_Path] * 函数用于创建一个路径对象OH_Drawin…

蜂窝物联云平台:一站式服务,智能生活从此开始!

蜂窝云平台 一、PC端展示与管理 GIS地图整合 在GIS地图上精确展示地块&#xff0c;轻松点选查看详细设备信息、实时监控和控制功能&#xff0c;以及基地的全方位介绍。 个性化定制界面 界面布局与功能展示均可按需求定制&#xff0c;打造独一无二的用户体验。 数据集中看板 将…

以进程完成并发的UDP服务端

网络(八)并发的UDP服务端 以进程完成功能 多进程处理 UDP客户端 // todo UDP发送端 #include <stdio.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/types.h> #include <stdlib.h> #includ…