深度剖析数据在内存中的存储

news2024/10/6 16:21:38

个人主页:平行线也会相交
欢迎 点赞👍 收藏✨ 留言✉ 加关注💓本文由 平行线也会相交 原创
收录于专栏【C/C++】
在这里插入图片描述

目录

  • 1.数据类型详细介绍
    • 1.1数据类型介绍
    • 1.2类型的基本归类
  • 2.整型在内存中的存储
  • 3.大小端字节序介绍及判断
    • 什么是大端小端:
    • 为什么会有大端和小端:
    • 设计程序判断机器大小端
    • 练习1
    • 练习2
      • `char`类型的范围是如何定义的
    • 练习3
    • 练习4
    • 练习5
    • 练习6
    • 练习7
  • 4.浮点型在内存中的存储解析

1.数据类型详细介绍

1.1数据类型介绍

我们已经知道了基本的内置类型:

char //字符数据类型
short //短整型
int //整型
long //长整型
long long //更长的整型
float //单精度浮点数
double //双精度浮点数
//以上类型都是C语言本身具有的类型,叫做内置类型
//C语言类型分为两类,其一就是上面的内置类型,其二就是自定义类型(也称构造类型)

类型的意义:1.类型决定了开辟空间的大小(大小又决定了使用范围)。2.看待内存空间的视角不同。
对于意义2,我们用代码举一个例子:在这里插入图片描述
在这里插入图片描述
意义2的意思就是站在整型的角度,内存中存放的当然是整型了;而站在浮点型的角度,内存中存放的当然是浮点型了。

1.2类型的基本归类

整型家族

char
	unsigned char
	signed char
short
	unsigned short [int]
	signed short [int]
int
	unsigned int
	signed int
long
	unsigned long [int]
	signed long [int]

有些小伙伴看到列举的整型家族中有char会感到疑问,char类型怎么能在整型家族中呢?是这样的:由于char类型不好归类,而且char类型在内存中存储的是其ASCII码值,既然存储的是ASCII码值的话,ASCII码值又是一个整数,相当于一个字符在表示的时候是用整数来表示和存储的。因此我们把char归类到整型家族中去。在char类型中又分为有符号(八个比特位中最高位为符号位,如:01 01 00 01)和无符号(八个比特位中最高位不是符号位,如:00 01 00 01),无符号为也就没有正负之分。
对于无符号数如果把最高位不当成符号位而当成有效位的话,它能表示的数的范围会更大一些。比如:11111111这八个比特位如果最高位这一位不是符号位而是有效位,则把二进制11111111翻译成十进制的话是255;把最高位当成有符号位的话用十进制数来表示是一个负数,即-127
其实一个char类型的变量如果表示有符号数的话,它的范围是-128127;而如果表示无符号是,它的范围是0255
浮点型家族

float//单精度浮点型
double//双精度浮点型

构造类型(即自己创造的一些类型):

数组类型
结构体类型  struct
枚举类型    enum
联合类型    enum

指针类型

int *pi;
char *pc;
float *pf;
void* pv;

空类型:

void表示空类型(无类型)
通常应用于函数的返回类型、函数的参数、指针类型

例如:
在这里插入图片描述

2.整型在内存中的存储

我们知道一个变量的创建是要在内存中开辟空间的。空间的大小是根据不同类型数据决定的。

接下来我们讨论数据在所开辟的内存中到底是如何存储的?
在这里插入图片描述
在这里插入图片描述
在清楚上面图片是什么意思的话,我们需要清楚原码、反码、补码的概念。这里不进行展开说明。

#include<stdio.h>
int main()
{
	int a = 20;
	//00000000000000000000000000010100原码
	//00000000000000000000000000010100反码
	//00000000000000000000000000010100补码
	int b = -10;
	//10000000000000000000000000001010原码
	//11111111111111111111111111110101反码
	//11111111111111111111111111110110补码
	return 0;
}

这里的二进制在内存中展示的时候是以16进制进行展示的(4个二进制位相当于1个16进制位)

#include<stdio.h>
int main()
{
	int a = 20;
	//00000000000000000000000000010100原码
	//00000000000000000000000000010100反码
	//00000000000000000000000000010100补码
	//0x00000014
	int b = -10;
	//10000000000000000000000000001010原码
	//11111111111111111111111111110101反码
	//11111111111111111111111111110110补码
	return 0;
}
#include<stdio.h>
int main()
{
	int a = 20;
	//00000000000000000000000000010100原码
	//00000000000000000000000000010100反码
	//00000000000000000000000000010100补码
	//00000014
	int b = -10;
	//10000000000000000000000000001010原码
	//11111111111111111111111111110101反码
	//11111111111111111111111111110110补码
	//0xFFFFFFF6
	return 0;
}

直到这里我们知道内存中存一个整数的时候存的是其二进制序列的补码,相信大家依然会有一些疑问:
在这里插入图片描述
为什么这里的14 00 00 00f6 ff ff ff是倒着存放的,但是不管怎么讲,整数在内存中存放的是其二进制序列的补码。
总结:整数存放内存中其实存放的是补码。
那为什么呢?

在计算机系统中,数值(这里指整数)一律用补码来表示和存储。原因在于,使用补码,可以将符号位和数值域统一处理,同时,加法和减法也可以统一处理(CPU只有加法器);此外,补码和原码相互转换其运算过程是相同的,不需要额外的硬件电。

刚刚提到CPU中只有加法器,但是当我们使用补码时,加法、减法等就可以进行统一处理了。这里它是怎么进行统一处理的呢?我们举一个例子:
在这里插入图片描述
对于乘法和除法的话不就是多加几次的事吗

3.大小端字节序介绍及判断

对于刚刚这段代码:
在这里插入图片描述
我们发现0x00 00 00 14在内存中是倒着放的(即14 00 00 00),如果我们想解决这个问题,我们就需要知道大小端的概念。

什么是大端小端:

大端(存储)模式是指数据的低位保存在内存的高地址中,而数据的高位,保存在内存的低位中;
小段(存储)模式是指数据的低位保存在内存的低地址中,而数据的高位,保存在内存的高地址中;

在这里插入图片描述

为什么会有大端和小端:

这是因为在计算机系统中,我们是以字节为单位的,每个地址单元都对应着一个字节,一个字节为 8bit。 但是在C语言中除了8bit的char之外,还有16bit的short型,32bit的long型(要看具体的编译器),另外,对于位数大于 8位的处理器,例如16位或者32位的处理器,由于寄存器宽度大于一个字节,那么必然存在着一个如何将多个字节安排的问题。

设计程序判断机器大小端

现在我们写一段代码来告诉我们当前机器的字节序是什么。
2

在这里插入图片描述
现在我们把这段程序分装成一个函数:

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

在这里有必要在回顾一下:指针类型决定了指针在进行解引用操作时能过访问几个字节。

我们先以int*类型的指针为例:
在这里插入图片描述
我们可以看到int*类型的指针在进行解引用操作时可以访问4个字节的大小。
下面我们在举一个char*类型的指针:
在这里插入图片描述
这里我们依然可以发现char*类型的指针在进行解引用是只能访问一个字节。
再次强调指针类型决定了指针在进行解引用时可以访问空间的大小。

练习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;
}
#include<stdio.h>
int main()
{
	char a = -1;
	//补码:11111111111111111111111111111111
	//当我们要把-1的二进制序列存放到a中去,a只能存放8个比特位
	//故a中存放的是11111111
	//a整型提示后:11111111111111111111111111111111
	signed char b = -1;
	//补码:11111111111111111111111111111111
	//当我们要把-1的二进制序列存放到b中去,b也只能存放8个比特位
	//故b中存放的是11111111
	//b整型提示后:11111111111111111111111111111111
	unsigned char c = -1;
	//c中存放的是11111111
	//c整型提示后:11111111111111111111111111111111
	//虽然a、b、c中存放的内容都是11111111,但是当我们再把它们拿出来的时候就不一样了。
	//如果要把a、b、c的整型打印出来,那我们就需要计算出a、b、c的整型形式,
	//所以就需要对a、b、c进行整型提升(整型提升按照原符号进行提升,无符号数进行整型提升时补0)
	printf("a=%d,b=%d,c=%d\n", a, b, c);
	//-1  -1  255
	return 0;
}

练习2

//以下程序输出什么
#include<stdio.h>
int main()
{
	char a = -128;
	printf("%u\n", a);
	return 0;
}
//以下程序输出什么
#include<stdio.h>
int main()
{
	char a = -128;
	//10000000000000000000000010000000---原码
	//11111111111111111111111101111111---反码
	//10000000000000000000000010000000---补码
	//10000000
	//由于要打印无符号十进制数字,故需要对10000000进行整型提升
	//整型提升之后:11111111111111111111111110000000---这依然是补码
	//按照正常道理我们需要把补码转换为原码来获得最终的结果,但注意这里是%u,即按照无符号数来进行打印
	//所以说计算机认为内存中存放的是一个无符号数,既然是这样的或,原、反、补码是相同的
	//所以直接把11111111111111111111111110000000拿出来充当我们的原码
	//最终结果为:4294967168
	printf("%u\n", a);//%u是打印十进制的无符号数字
	return 0;
}

char类型的范围是如何定义的

在这里插入图片描述
在这里插入图片描述

练习3

//以下输出结果是什么
#include<stdio.h>
int main()
{
	char a = 128;
	printf("%u\n", a);
	return 0;
}

这里的变量achar类型的,所以根本存不下128,这里的128就是127+1,即127+1其实就是练习2中的-128,所以说这里变量a存放的就是-128,因此输出结果和练习2一样。即:
在这里插入图片描述

注意:把练习2和3对比着进行加深理解。

练习4

//以下输出结果是什么
#include<stdio.h>
int main()
{
	int i = -20;
	unsigned int j = 10;
	printf("%d\n", i + j);
	//可以按照补码的形式进行运算,最后格式化成整数
	return 0;
}

在这里插入图片描述
未来再遇到这种题时不要害怕,大不了不就是拿起笔来算一算嘛😀

练习5

//以下输出结果是什么
#include<stdio.h>
int main()
{
	unsigned int i;
	for (i = 9; i >= 0; i--)
	{
		printf("%u\n", i);
	}
	return 0;
}

在这里插入图片描述

打印时我们打印的是i,i又通过%u来打印,所以打印出来的是无符号的整数,不管是一个什么样的数字都会当作无符号数(永远>=0)来进行打印,打印出来的都是>0的数字,即使是一个负数进去,站在i的角度它都会认为是一个正数。所以说结果是一个死循环。
当i减到-1、-2、-3、-4…时,-1、-2、-3…的补码被当作整数的补码进行输出。这一点尤其要注意

练习6

//以下输出结果是什么
#include<stdio.h>
#include<string.h>
int main()
{
	char a[1000];
	int i;
	for (i = 0; i < 1000; i++)
	{
		a[i] = -1 - i;
	}
	printf("%d\n", strlen(a));
	return 0;
}

-1、-2、-3、-4…-998、-999、-1000这1000个数字如果真的存放到数组a中,任何一个数字放到数组a中去都会转换为-128->127之间的一个数字。
在这里插入图片描述
还记的这个圆吗,当i从-128到-129时我们发现又循环回去了,-128-1得到的结果时正的127,不可能得到-129.
数组a中存放的数:-1、-2、-3、-4…-128、127、126、125…2、1、0、-1、-2、-3…。所以程序最终运行的结果为255。即:
在这里插入图片描述
还要注意一个点:数字0和字符’0’不是一回事。\0其实就是数字0其对应的ASICC码值是0;而字符’0’对应的ASICC码值是48。

练习7

//以下输出结果是什么
#include<stdio.h>
unsigned char i = 0;
int main()
{
	for (i = 0; i <= 255; i++)
	{
		printf("hello world\n");
	}
	return 0;
}

这里的char类型是unsigned char,unsigned char类型存放的数的范围是0->255,而判断中的i<=255这个条件就恒成立,所以程序结果依然是死循环。
此题可以与练习5进行比较学习。
所以我们今后再使用无符号数时,如果条件把握的不合适,判断其是不是大于小于等于某个数时,极有可能导致程序死循环,无符号数很容易导致程序陷入死循环。在今后写代码过程中一定要特别注意无符号数。
至此练习题到此结束,这7道练习题跟数据在内存中的存储有着非常大的关系。一定要把这7道题理解透。

4.浮点型在内存中的存储解析

常见的浮点数:

3.14159 1E10(1.0*10^10)
浮点数家族:float 、double、 long double类型。

浮点数存储的例子:

#include<stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);

	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为%f\n", *pFloat);
	return 0;
}

再继续往下看之前,请务必思考一下上面的举例,想一想程序运行的结果是什么?
下面请看程序运行结果:
在这里插入图片描述
程序结果是不是和读者想的是一样的呢?如果是,那恭喜读者对浮点数在内存中的存储有着不错的理解,倘若不是的话,别灰心,接下来我会逐步的对这道题进行分析:
我们首先要知道整型和浮点型在内存中存储的方式是截然不同的。对于整型,其在内存中是以二进制序列的补码进行存储的(涉及到大端小端);那浮点数在内存中是怎样存储的呢?
请看:
根据国际标准IEEE(电气和电子工程协会)规定,任何一个浮点数NUM的二进制数可以写为:
NUM = (-1) ^ S * M * 2 ^ E
(这里S表示符号,E表示阶乘,M表示有效数字)
①当S为0时,表示一个正数;当S为1时,表示负数
②M表示有效数字,1<= M <2
③2^E表示指数

(-1) ^ S意思就是你要表示的数是一个正数还是一个负数,它就相当于一个符号位。
那M为什么1<= M <2呢?是这样的,科学计数法表示的二进制里是不可能出现2这个数的,所以我们要把它化成有效数字时就是1点多少多少。
2^E表示的是指数位

我们就拿9.0进行举例,可以表示为:

(-1)^0 *1.001 * 2^3
这里S=0 M=1.001 E=3
(-1) ^ S * M * 2 ^ E

所以浮点数在内存中存储的话我们只需要把S M E这些值存起来,我们就可以还原回来真实的浮点数是几。真正的IEEE754规定的确实是我们只要把S M E相关的一个值存放到内存中去,回头我们在回复回来就可以。但举例到底是怎么存储的呢?假设我们把一个浮点数首先由十进制写成二进制,之后再把这个二进制写成科学计数法即(-1) ^ S * M * 2 ^ E的表示形式,求出S M E的时候,这个时候我们再把S M E相关的值存起来,怎么存的呢?请看:
IEEE 754规定:对于32位(32个比特位)的浮点数,最高的一位是符号位S,接着的8位是指数E,剩下的23位是有效数字M
在这里插入图片描述
对于64位的浮点数,最高的1位是符号位S,接着的11位是指数E,剩下的52位为有效数字M。
在这里插入图片描述
在这里插入图片描述

既然把S M E划分的三块空间之后,是不是把这些值直接扔到里面去就可以呢?当然不是这样的。请接着往下看:
IEEE 754对有效数字M和指数E,还有一些特别规定。前面说过,1<= M <2,也就是说,M可以写成1.xxxxxx的形式,其中xxxxxx表示小数部分。
IEEE 754规定,在计算机内部保存M是,默认这个数的第一位总是1,因此可以被舍去,只保存后面的xxxxxx部分。比如保存1.01是,只保存01,等到读取的时候,再把第一位的1加上去。这样做的目的,是节省1位有效数字。以32位浮点数为例,留给M只有23位,将第一位的1舍去以后,等于可以保存24位有效数字。
至于指数E,情况就比较复杂了。
首先,E作为一个无符号整数(unsigned int),这就意味着,如果E为8位,它的取值范围为0-255;如果E为11为,它的取值范围为0-2047。但是我们知道,科学计数法中的E是可以出现负数的,所以IEEE 754规定,存入内存时E的真实值必须再加上一个中间数,对于8为的E,这个中间数是127;对于11为的E,这个中间数是1023。比如,2^10的E是10,所以保存成32为浮点数是,必须保存成10+127=137,即10001001。
举个例子

0.5
(-1)^0 * 1.0 *2^(-1)
S=0
M=1.0
E=-1
E+127=126(意思是虽然我们计算出来的结果为-1,但我们真正存放到内存中的那个值是126,真实值要减去127,所以倒着推过去可以得到真实值为-1。)

现在,我们重现整理一下思路:我们把一个十进制的浮点数首先写成一个二进制的浮点数,然后把它转换成科学计数法的表现形式,此时就有的M S E。S直接存进去就好了;M要去点小数点前面的1然后存进去;至于E要给它加一个中间值之后给它存进去。
我们用代码来简单验证一下:
在这里插入图片描述

.
.
.
以上我们是讨论是如何放进去,而指数E从内存中往外取的时候又分为三种情况
E不为全0或不为全1

这是,浮点数就采用下面的规则表示,即指数Education计算值减去127(1023),得到真实值,再将有效数字M前加上第一位的1。比如:0.5(1/2)的二进制形式为0.1,由于规定正数部分必须为1,即将小数点右移1位。则为
1.0*2^(-1),-1+127=126,表示为01111110,而尾数1.0去掉整数部分为0,补齐0到23位0000000000000000000000000000,则其二进制表示形式为:
0 01111110 0000000000000000000000000000

E为全0

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

E为全1

这时,如果有效数字M全为0,表示±无穷大(正负取决于符号位)。

好了,关于浮点数的表示规则就说到这里。

现在我们回到之前未讲解的题目😜

#include<stdio.h>
int main()
{
	int n = 9;
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);
	printf("*pFloat的值为:%f\n", *pFloat);

	*pFloat = 9.0;
	printf("num的值为:%d\n", n);
	printf("*pFloat的值为%f\n", *pFloat);
	return 0;
}
#include<stdio.h>
int main()
{
	int n = 9;
	//0 00000000 00000000000000000001001-补码
	float* pFloat = (float*)&n;
	printf("n的值为:%d\n", n);//9
	printf("*pFloat的值为:%f\n", *pFloat);//0.000000
	//(-1)^0 * 0.00000000000000000001001 * 2^(-126)

	*pFloat = 9.0;
	//1001.0
	//1.001*2^3
	//(-1)^0 * 1.001 * 2^3   这里E为3,存的时候要加上127变为130,即10000010
	//0  10000010  00100000000000000000000这就是9.0存的内存的形式

	printf("num的值为:%d\n", n);//这个时候要打印n的话,
	//既然要打印n(n是一个整数)就要站在n的角度,认为内存中存的是一个整数的补码,
	//即01000001000100000000000000000000,这也是这个整数的原码
	//01000001000100000000000000000000转换为十进制为1091567616
	printf("*pFloat的值为%f\n", *pFloat);//9.0
	return 0;
}

在这里插入图片描述
到这里相信大家对浮点数在内存中的存储有了一定的了解。原来是浮点数的形式放进去和以整型的形式放进去的方式是不一样的,取出来的方式也不一样。所以,整型的形式放进去再以浮点型的形式取出来得到的结果肯定是不正确的,同理以浮点型的形式放进去再以整型的形式取出来得到的结果肯定也是不正确的。所以,浮点数就应该按照浮点数的形式存,按照浮点数的形式取;整型就应该按照整型的方式存,按照整型的方式取。
之所以我们要了解数据在内存中的存储是因为,在未来我们遇到某些特殊的值比较怪异时,我们有能力去分析它到底结果是怎样的

到这里,整个数据在内存中的存储的讲解就结束了。
本文至此结束,感谢各位🙇‍。

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

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

相关文章

[附源码]Python计算机毕业设计茶叶产品质量安全可追溯系统

项目运行 环境配置&#xff1a; Pychram社区版 python3.7.7 Mysql5.7 HBuilderXlist pipNavicat11Djangonodejs。 项目技术&#xff1a; django python Vue 等等组成&#xff0c;B/S模式 pychram管理等等。 环境需要 1.运行环境&#xff1a;最好是python3.7.7&#xff0c;…

尚医通 (二十八) --------- 医院管理相关 (引入注册中心、远程调用)

目录一、医院管理医院管理效果展示二、注册中心与服务调用1. Nacos 概述2. 注册服务三、医院管理实现1. 医院列表2. service-cmn 模块提供接口3. 封装 Feign 服务调用4. 医院接口远程调用数据字典5. 添加数据字典显示接口6. 医院列表前端一、医院管理 目前我们把医院、科室和排…

函数栈帧的创建和销毁

“总有人间一两风&#xff0c; 填我十万八千梦” &#x1f351;作者&#xff1a;小赛毛 &#x1f495;文章初次日期&#xff1a;2022/11/21 目录 函数栈帧解决了什么问题&#xff1f; 什么是栈&#xff1f; 什么是寄存器&#xff1f; 函数栈帧的创建和销毁 预热知识准备&a…

Flink DataStream API 介绍

Flink DataStream API 介绍 StreamExecutionEnvironment #mermaid-svg-JKeWa22W2vWA4zBS {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-JKeWa22W2vWA4zBS .error-icon{fill:#552222;}#mermaid-svg-JKeWa22W2vWA4z…

使用element-ui实现树形穿梭框

<template><div class"transferTreeBox"><!-- 左侧待选内容 --><div class"SelectBox"><div class"boxTitle" click"clickAllSelect">全选 ></div><div class"boxCenter"><…

【Hack The Box】Linux练习-- Frolic

HTB 学习笔记 【Hack The Box】Linux练习-- Frolic &#x1f525;系列专栏&#xff1a;Hack The Box &#x1f389;欢迎关注&#x1f50e;点赞&#x1f44d;收藏⭐️留言&#x1f4dd; &#x1f4c6;首发时间&#xff1a;&#x1f334;2022年9月7日&#x1f334; &#x1f36d…

dumi 2,它来了它来了它来了

dumi 1.0 在 2020 年 3 月 2 日正式发布&#xff0c;到今天一共有 80 位 Contributor、提交 1100 Commit、为近 4000 个开源项目提供了组件库/站点的文档方案&#xff1b;dumi 作为一个 GitHub 数亿开源项目中的渺小一粒&#xff0c;能有这么多人共同参与、能为这么多项目提供价…

【JAVA程序设计】(C00097) 基于SSM的果树溯源可视化管理系统

基于SSM的果树溯源可视化管理系统项目简介项目获取开发环境项目技术运行截图项目简介 基于ssm框架的果树溯源可视化管理系统&#xff0c;本系统分为二种用户&#xff1a;管理员、农户 管理员角色包含以下功能&#xff1a; 登录、农户管理、商家管理、果树管理、地块管理、农资…

马上2023年了,终于发现一款颜值爆表的记账软件

不知道大家平时有没有记账的习惯&#xff0c;我是在疫情之后&#xff0c;才开始记账的。 记账之后&#xff0c;的确发现了很多问题。尤其是自己花钱大手大脚没有规划的毛病。 后来&#xff0c;在每个月第1周&#xff0c;我都会分析一下上一个月的账目&#xff0c;看看自己的收…

同花顺_代码解析_交易系统_J09_18

本文通过对同花顺中现成代码进行解析&#xff0c;用以了解同花顺相关策略设计的思想 目录 J_09 抛物线转向系统 J_10 均线系统 J_11 随机指标专家 J_12 顺势指标 J_15 动量线 J_16 心理线 J_17 变动速率 J_18 相对强弱指标 J_09 抛物线转向系统 指标标识由绿变红时为买…

LeetCode287之寻找重复数(相关话题:二分查找,快慢指针)

题目描述 给定一个包含 n 1 个整数的数组 nums &#xff0c;其数字都在 [1, n] 范围内&#xff08;包括 1 和 n&#xff09;&#xff0c;可知至少存在一个重复的整数。 假设 nums 只有 一个重复的整数 &#xff0c;返回 这个重复的数 。 你设计的解决方案必须 不修改 数组 …

【SIFT】超详详详解 - 实现细节记录

目录前言一、尺度空间的生成&#xff1a;高斯金字塔 Gaussian pyrmid1、图像的尺度空间 - 高斯金字塔 Gaussian pyramid2、高斯金字塔的组 与 组数 Octave1&#xff09;组2&#xff09;组数3&#xff09;升采样获得 base image3、高斯金字塔的层与层数 interval31&#xff09;层…

2022年轨道交通行业研究报告

第一章 行业概况 轨道交通是指运营车辆需要在特定轨道上行驶的一类交通工具或运输系统。最典型的轨道交通就是由传统火车和标准铁路所组成的铁路系统。随着火车和铁路技术的多元化发展&#xff0c;轨道交通呈现出越来越多的类型&#xff0c;不仅遍布于长距离的陆地运输&#x…

k8s基础命令及Linux上用Kubectl(k8s)部署Nginx

k8s基础命令及Linux上用Kubectl(k8s)部署Nginx 不懂K8s搭建的可以看我这篇文章 Linux上部署Kubectl(k8s) 1.k8s简介 1.1 Kubernetes 概念 在 k8s 上进行部署前&#xff0c;首先需要了解一个基本概念 Deployment Deployment 译名为 部署。在k8s中&#xff0c;通过发布 Depl…

积分商城小程序的作用_分享积分商城小程序开发的效果

积分商城系统带来的6点作用分别是&#xff1a;对商家的依赖性、提升转化和复购、运营模式多元化、提升收益、进行积分营销、进行口碑传播&#xff0c;下面我们就来详细的了解一下。 积分商城系统带来的作用一&#xff1a;对商家的依赖性 积分商城系统是进行积分兑换的&#xf…

渗透测试CTF-图片隐写的详细教程2(干货)

上篇文章我们介绍了这7个工具&#xff0c;这里简单的介绍一下。 Binwalk 用来检测图片中是否有隐藏的文件。 Foremost 将图片中的隐藏文件拆分出来。 010Editor ①修改图片的参数来查看隐藏信息。 ②查看压缩包是否是伪加密。 Stegsolve.jar 图片隐写查看神器。 OurSecret 1个图…

公众号免费查题功能搭建

公众号免费查题功能搭建 本平台优点&#xff1a; 多题库查题、独立后台、响应速度快、全网平台可查、功能最全&#xff01; 1.想要给自己的公众号获得查题接口&#xff0c;只需要两步&#xff01; 2.题库&#xff1a; 题库&#xff1a;题库后台&#xff08;点击跳转&#xf…

Word处理控件Aspose.Words功能演示:在 Java 中将文本转换为 PNG、JPEG 或 GIF 图像

在各种情况下&#xff0c;通常需要进行文本到图像的转换&#xff0c;例如&#xff0c;使文本成为只读。在上一篇文章中&#xff0c;我们写过如何将TXT文件中的文本转换为 Java 中的 PDF。在本文中&#xff0c;您将学习如何在 Java 中以编程方式将文本转换为PNG、JPEG或GIF图像。…

B. Catching Cheaters(最长公共子序列变形)

Problem - 1446B - Codeforces 给你两个字符串A和B&#xff0c;代表两个涉嫌作弊的学生的论文。对于任何两个字符串C&#xff0c;D&#xff0c;我们将其相似性分数S(C,D)定义为4⋅LCS(C,D)-|C|-|D|&#xff0c;其中LCS(C,D)表示字符串C和D的最长公共子序列。 你认为只有部分文…

三次握手与四次挥的问题,怎么回答?

在面试中&#xff0c;三次握手和四次挥手可以说是问的最频繁的一个知识点了&#xff0c;我相信大家也都看过很多关于三次握手与四次挥手的文章&#xff0c;今天的这篇文章&#xff0c;重点是围绕着面试&#xff0c;我们应该掌握哪些比较重要的点&#xff0c;哪些是比较被面试官…