C生万物 | 从浅入深理解指针【最后部分】

news2024/11/25 4:30:09

C生万物 | 从浅入深理解指针【最后部分】

文章目录

  • C生万物 | 从浅入深理解指针【最后部分】
    • 前言
    • sizeof和strlen的对比
      • sizeof
      • strlen
    • 数组和指针笔试题解析
      • 一维数组
      • 字符数组
      • 二维数组

前言

  • 我们前面学了四个部分了,如果没有看前面的建议可以看一下前面的~~

  • C生万物 | 从浅入深理解指针【第一部分】

  • C生万物 | 从浅入深理解指针【第二部分】

  • C生万物 | 从浅入深理解指针【第三部分】(转移表的实现)

  • C生万物 | 从浅入深理解指针【第四部分】(qsort的使用和模拟实现)


  • 接下来我们开始我们指针的最后一个部分,来加深对指针的印象~~

sizeof和strlen的对比

sizeof

  • 在学习操作符的时候,我们学习了sizeofsizeof 计算变量所占内存内存空间大小的,单位是字节,如果操作数是类型的话,计算的是使用类型创建的变量所占内存空间的大小。

  • 我们就来开始学习了解sizeof~~


  • 其中size_t其实专门是设计给sizeof的,表示sizeof的返回值类型
  • sizeof计算的不可能是负数吧,所以size_t是为sizeof来设计的~~

列如:

int main()
{
	int a = 10;
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(int));
	return 0;
}

在这里插入图片描述

  • 如果这里是变量,括号是可以省略的
  • 如果是类型就是,就不能省略

在这里插入图片描述

  • 这里算出的4就是占用4个字节

  • sizeof 只关注占用内存空间的大小,不在乎内存中存放什么数据,我们一会来详细看~~

strlen

strlen 是C语言库函数,功能是求字符串长度。函数原型如下:

size_t strlen ( const char * str );

它统计的是从strlen函数的参数str中这个地址开始向后,\0之前字符串中字符的个数。
strlen 函数会一直向后找\0 字符,直到找到为止,所以可能存在越界查找。

我们来看下面的代码

int main()
{
	char arr2[] = "abc";
	printf("%d\n", strlen(arr2));
	return 0;
}
  • 这里的strlen算出的是几?3
  • 我们还可以通过调试窗口看一下是怎么存放的~~

在这里插入图片描述

  • 可以看到这里内存监视窗口的61就是97,0就是\0strlen是统计\0之前的字符串的个数,结果是3

在这里插入图片描述

  • 那我在字符串的中间手动加一个\0会算出几呢?
char arr2[] = "ab\0c";
printf("%d\n", strlen(arr2));
  • 可以看到结果是3

在这里插入图片描述

  • 那字符串没有\0它的结果是什么呢?
char arr1[] = { 'a', 'b', 'c' };
printf("%d\n", strlen(arr1));
  • 我们可以看到结果是15,其实是随机值,我也不知道多会会遇到\0

在这里插入图片描述

在这里插入图片描述

  • 下面我们来对比一下strlensizeof

strlen:

  • sizeof是操作符
  • sizeof计算操作数所占内存的大小,单位是字节
  • 不关注内存中存放什么数据

sizeof:

  • strlen是库函数,使用需要包含头文件string.h
  • srtlen是求字符串长度的,统计的是\0之前字符的个数
  • 关注内存中是否有\0,如果没有\0,就会持续往后找,可能会越界

  • sizeof在计算大小的时候,其实是根据类型推算的
  • 那么下面打印的是什么呢?
short s = 10;
int i = 2;
int n = sizeof(s = i + 4);
printf("%d\n", n);
printf("%d\n", s);
  • 我们来看结果~~

在这里插入图片描述

  • 为什么是2和10呢?我们来分析一下~~

  • 创建了一个短整型s,占两个字节,i是整形,占四个字节

  • 这里的i+4得出的结果我要放到s类型,我一个4个整形的放到两个整形的空间,这要发生截断,截断之后就是s说了算,所以就是2个字节。

  • 那么第二个,表达式放到sizeof内部不会真实计算的,不参与计算!!!所以原来的值就会打印什么值~~


  • 那么有同学会问,表达式不参与计算,那上面那个为什么会是2呢?其实是sizeof是根据类型推断出来的,s = i + 4不会执行,其中 i + 4算出的就是整形类型的,整形类型的结果要放到shot类型的,所以就是short类型,就是2个字节,你懂了吗~~

如果还没有理解的话,我们来看一些笔试题,来加深一下印象~~

数组和指针笔试题解析

一维数组

  • 我们先来看这里,下面打印的是什么呢?可以先自己分析一下,然后我们来挨个分析~~
int main()
{
	int a[] = { 1,2,3,4 };
	printf("%d\n", sizeof(a));
	printf("%d\n", sizeof(a + 0));
	printf("%d\n", sizeof(*a));
	printf("%d\n", sizeof(a + 1));
	printf("%d\n", sizeof(a[1]));
	printf("%d\n", sizeof(&a));
	printf("%d\n", sizeof(*&a));
	printf("%d\n", sizeof(&a + 1));
	printf("%d\n", sizeof(&a[0]));
	printf("%d\n", sizeof(&a[0] + 1));
	return 0;
}
  • 你要知道的就是数组名即为首元素地址,不过有两个例外:
    • sizeof(数组名) —— 数组名表示整个数组,计算的是整个数组的大小,单位是字节
    • &数组名 —— 数组名表示数组名表示整个数组,取出的是整个数组的地址。

  • sizeof内部单独放了一个数组名,数组名表示整个数组的大小,数组内有4个元素,每个元素4个字节,所以就是16
printf("%d\n", sizeof(a));
  • 这个地方的数组名的a并没有放到sizeof内部,也没有&,所以a就是首元素的地址,是地址,大小就是4/8个字节
printf("%d\n", sizeof(a + 0));
  • a就是数组首元素的地址,a==&a[0],*a 其实就是第一个元素,也就是a[0],大小就是4个字节
printf("%d\n", sizeof(*a));
  • a就是数组首元素的地址(&a[0] -->int*), a+1–> &a[1],a+1就是第二个元素的地址,所以结果就是4/8
printf("%d\n", sizeof(a + 1));
  • 计算第2个元素的大小,单位是字节 结果就是4
printf("%zd\n", sizeof(a[1]));
  • &a 取出的是数组的地址,但是数组的地址也是地址,是地址大小就是4 / 8 个字节
printf("%zd\n", sizeof(&a));
  • 这里&a是取出数组的地址,然后再解引用,也就是相当于抵消了,&a是一个数组指针,也就是int(*p)[4] = &a,*p访问一个数组的大小,p+1就是跳过一个数组的大小,结果是16
printf("%d\n", sizeof(*&a));
  • &a+1是跳过整个数组后的地址,是地址大小就是4/8个字节,结果就是4/8
printf("%zd\n", sizeof(&a + 1));
  • 这里就是首元素的地址,结果是4/8
printf("%zd\n", sizeof(&a[0]));
  • 这里就是第二个元素的地址,结果是4/8
printf("%zd\n", sizeof(&a[0] + 1));
  • 我们在vs上验证一下,这个是32位平台下打印的~~

在这里插入图片描述

  • 这个是在64位下运行的~~

在这里插入图片描述


字符数组

  • 接下来我们来看字符数组
int main()
{
	char arr[] = { 'a','b','c','d','e','f' };
	printf("%d\n", sizeof(arr));
	printf("%d\n", sizeof(arr + 0));
	printf("%d\n", sizeof(*arr));
	printf("%d\n", sizeof(arr[1]));
	printf("%d\n", sizeof(&arr));
	printf("%d\n", sizeof(&arr + 1));
	printf("%d\n", sizeof(&arr[0] + 1));
	return 0;
}
  • 数组名单独放在了sizeof内部,计算的是整个数组的大小,字符有6个,所以结果就是6
printf("%d\n", sizeof(arr));
  • arr是数组首元素的地址,arr+0 还是首元素的地址 是地址大小就是4/8个字节
printf("%d\n", sizeof(arr + 0));
  • arr是数组首元素的地址,*arr就是首元素,就占一个字符大小就是1个字节
printf("%d\n", sizeof(*arr));
  • arr[1]就是数组的第二个元素,大小是1个字节
printf("%d\n", sizeof(arr[1]));
  • &arr 是数组的地址,数组的地址也是地址,大小就是4/8
printf("%d\n", sizeof(&arr));
  • &arr+1 是跳过整个数组,指向f的后面4/8
printf("%d\n", sizeof(&arr + 1));
  • &arr[0]是首元素的地址,&arr[0]+1就是第二个元素的地址 4/8
printf("%d\n", sizeof(&arr[0] + 1));
  • 我们来看32平台下

在这里插入图片描述

  • 再来看64位平台下的

在这里插入图片描述


  • 我们继续来看第二个
char arr[] = { 'a','b','c','d','e','f' };
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
  • 这个数组是没有\0的,strlen是计算\0之前的元素个数所以就是随机值
printf("%d\n", strlen(arr));
  • 这个数组名也是首元素的地址,+0也就相当于没有加,结果是随机值~~
printf("%d\n", strlen(arr+0));
  • 这里arr是首元素的地址,然后*arr解引用就是字符a,ASCLL码值是97,97传给strlen,会把97当成个地址,会非法访问,结果会报错

在这里插入图片描述

printf("%d\n", strlen(*arr));
  • 这个代码与上个代码相似,访问的是第二个元素的ASCLL码值,会当地址传过去,也会报错
printf("%d\n", strlen(arr[1]));
  • &arr就是取出这个数组的地址,也就是起始位置向后数,结果也是随机值
printf("%d\n", strlen(&arr));
  • 这个&arr就是首元素的地址,然后+1,跳过整个数组的地址,内存放的什么也不知道,结果也就是随机值
printf("%d\n", strlen(&arr+1));
  • &arr[0]是首元素的地址,+1就是第二个元素的地址,然后向后数,结果也是随机值
printf("%d\n", strlen(&arr[0]+1));

在这里插入图片描述


  • 这里我们初始化abcdef\0,这里面有\0~~
char arr[] = "abcdef";
printf("%d\n", sizeof(arr));
printf("%d\n", sizeof(arr+0));
printf("%d\n", sizeof(*arr));
printf("%d\n", sizeof(arr[1]));
printf("%d\n", sizeof(&arr));
printf("%d\n", sizeof(&arr+1));
printf("%d\n", sizeof(&arr[0]+1));
  • 这里算的是arr元素的大小,结果是7
printf("%d\n", sizeof(arr));
  • arr表示数组首元素的地址,arr + 0 还是首元素的地址,大小就是4/8个字节
printf("%d\n", sizeof(arr+0));
  • arr表示数组首元素的地址,*arr就是首元素,大小就是1字节
printf("%d\n", sizeof(*arr));
  • arr[1]是第二个元素,大小也是1字节
printf("%d\n", sizeof(arr[1]));
  • &arr是数组的地址,但是也是地址,是地址大小就是4/8个字节
printf("%d\n", sizeof(&arr));
  • &arr是数组的地址,&arr+1就是跳过整个数组的那个地址,结果是4/8个字节
printf("%d\n", sizeof(&arr+1));
  • 第二个元素的地址,大小4/8个字节
printf("%d\n", sizeof(&arr[0]+1));

在这里插入图片描述


  • 我们再把sizeof换成strlen~~
char arr[] = "abcdef";
printf("%d\n", strlen(arr));
printf("%d\n", strlen(arr+0));
printf("%d\n", strlen(*arr));
printf("%d\n", strlen(arr[1]));
printf("%d\n", strlen(&arr));
printf("%d\n", strlen(&arr+1));
printf("%d\n", strlen(&arr[0]+1));
  • arr是首元素的地址,计算的是strlen遇到\0之前元素的个数,结果是6
printf("%d\n", strlen(arr));
  • arr+1 也是首元素的地址,结果就是6
printf("%d\n", strlen(arr+0));
  • 这里结果是报错,会非法访问
printf("%d\n", strlen(*arr));
  • 这里也会形成非法访问~~
printf("%d\n", strlen(arr[1]));
  • &arr是数组的地址,但是这个地址也是指向数组的起始位置的,strlen就从起始位置开始向后找\0,结果是6
printf("%d\n", strlen(&arr));
  • &arr+1是跳过整个数组后的地址,从这里开始向后找\0,就是随机值
printf("%d\n", strlen(&arr+1));
  • arr[0] + 1 是第二个元素的地址,长度是5
printf("%d\n", strlen(&arr[0]+1));
  • 我们来看一下结果~~

在这里插入图片描述


  • 我们这里指针变量p存放的是这个字符串a的地址
char *p = "abcdef";
printf("%d\n", sizeof(p));
printf("%d\n", sizeof(p+1));
printf("%d\n", sizeof(*p));
printf("%d\n", sizeof(p[0]));
printf("%d\n", sizeof(&p));
printf("%d\n", sizeof(&p+1));
printf("%d\n", sizeof(&p[0]+1));
  • p是一个指针变量,大小是4/8个字节
printf("%d\n", sizeof(p));
  • p+1是‘b’的地址,是地址就是4/8个字节
printf("%d\n", sizeof(p+1));
  • *p 是首字符,大小是1字节
printf("%d\n", sizeof(*p));
  • p[0] === *(p+0),其实就是字符串中的首字符,大小是1字节
printf("%d\n", sizeof(p[0]));
  • &p是p的地址,也是地址,地址大小就是4/8个字节
printf("%d\n", sizeof(&p));
  • &p + 1也是地址,&p1+1是跳过p变量后的地址
printf("%d\n", sizeof(&p+1));
  • 4/8 – &p[0] + 1是b的地址
printf("%d\n", sizeof(&p[0]+1));

32位下

在这里插入图片描述

64位下

在这里插入图片描述

char *p = "abcdef";
printf("%d\n", strlen(p));
printf("%d\n", strlen(p+1));
printf("%d\n", strlen(*p));
printf("%d\n", strlen(p[0]));
printf("%d\n", strlen(&p));
printf("%d\n", strlen(&p+1));
printf("%d\n", strlen(&p[0]+1));
  • p指向这个字符串的首元素地址,字符串中有\0,从a的地址开始向后访问,结果就是6
printf("%d\n", strlen(p));
  • p的类型是char*+1跳过的就是一个char类型的数据,所以就来到了字符'b'的地址处,向后找\0的话就最后的结果即为 5
printf("%d\n", strlen(p+1));
  • *p取到的就是字符'a',strlen就会把字符a的ascll码值当地址传过去了,会产生非法访问,结果是err
printf("%d\n", strlen(*p));	
  • 这个和上一个一样,也是会产生非法访问,就相当于 *p == *(p+0) == p[0]
printf("%d\n", strlen(p[0]));
  • 这个结果就是随机值,&p是p的地址,类型是char*从p所占空间的起始位置开始查找的,它不知道什么时候会遇到\0,所以就会是随机值
printf("%d\n", strlen(&p));
  • 这个代码在&取地址后它的类型就变成了char**+1会跳过一个char*类型的数据,它指向了字符串末尾的这个位置,从这里向后去进行找\0,也是不知道什么时候会遇到,所以最后的结果还是随机值
printf("%d\n", strlen(&p+1));
  • 这里和第二个很相似,&和[]就相当于抵消了,+1就指向了'b',结果也就是5
printf("%d\n", strlen(&p[0]+1));

在这里插入图片描述


最后我们再来看二维数组,也是比较难的一部分

二维数组

int a[3][4] = {0};
printf("%d\n",sizeof(a));
printf("%d\n",sizeof(a[0][0]));
printf("%d\n",sizeof(a[0]));
printf("%d\n",sizeof(a[0]+1));
printf("%d\n",sizeof(*(a[0]+1)));
printf("%d\n",sizeof(a+1));
printf("%d\n",sizeof(*(a+1)));
printf("%d\n",sizeof(&a[0]+1));
printf("%d\n",sizeof(*(&a[0]+1)));
printf("%d\n",sizeof(*a));
printf("%d\n",sizeof(a[3]));
  • sizeof(数组名),计算的就是整个数组的大小,这是一个二维数组,数组是三行四列的,总共十二个元素,每个元素的类型是int,为4个字节,那么总的大小就是 48
printf("%d\n", sizeof(a));
  • a[0][0]代表的是数组第一行第一列的元素,所以每个元素都是4个字节
printf("%d\n", sizeof(a[0][0]));
  • a[0]为第一行的数组名,而且它是单独放在sizeof()内部的,计算的是第一行这一整行的大小,里面有4个元素,每个元素都是4个字节,那么结果即为16
printf("%d\n", sizeof(a[0]));
  • a[0]是第一行这个数组的数组名,但是数组名并非单独放在sizeof内部,所以数组名表示数组首元素的地址,也就是a[0][0]的地址,a[0]+1是第一行第二个元素a[0][1]的地址,地址的大小是4/8个字节
printf("%d\n", sizeof(a[0] + 1));
  • a[0] + 1是第一行第二个元素a[0][1]的地址,*(a[0] + 1)就是第一行第二个元素,大小是4个字节
printf("%d\n", sizeof(*(a[0] + 1)));
  • a没有单独放在sizeof内部,没有&,数组名a就是数组首元素的地址,也就是第一行的地址,a+1,就是第二行的地址,也就是等价于a -- int(*)[4] ---->a+1 -- int(*)[4]
printf("%d\n", sizeof(a + 1));
  • 下面这个也就是对这一行解引用,那么也就得到了第二行这一整行,此时计算是这一整行的大小,结果为16
printf("%d\n", sizeof(*(a + 1)));
  • 这个和上一个一样,只是换了一种写法,等价于*(a + 1),计算的是第二行的元素大小,结果是16
printf("%d\n", sizeof(a[1]));
  • a[0]为第一行的数组名,对它进行取地址就取到了这一整行的地址,它的类型也为一个数组指针int (*)[4],那 +1的话也会跳过整个数组,此时也就来到了第二行,那么取到的便是第二行的地址,地址的大小即为 4/8个字节
printf("%d\n", sizeof(&a[0] + 1));
  • 这里和上面那个相似,第二行解引用,算的是第二行元素的大小,结果是16
printf("%d\n", sizeof(*(&a[0] + 1)));
  • 数组名a就是数组首元素的地址,也就是第一行的地址,*a就是一行的 等价于*(a+0) == a[0]
printf("%d\n", sizeof(*a));
  • 这个二维数组不是只有三行吗,第三行的数组名为a[2],那a[3]不是越界了吗?

  • 要知道,对于任何一个表达式来说具有2个属性,一个是【值属性】,一个是【类型属性】

  • 例如3 + 5 = 8,它的值属性就是数字8,类型属性即为int但对于【sizeof()】来说,它在计算的时候只需要知道【类型属性】就可以了,类似我们之前写过的sizeof(int)、sizeof(char)等等,对这些内置类型就可以计算出它的大小,并没有去实际地创造出空间

  • 那么对于下面这个a[3]来说,虽然看上去存在越界,但是sizeof()并不关心你有没有越界,而是知道你的类型即可,那么a[3]便是二维数组的第四行,虽然没有第四行,但是类型是确定的,那么大小就是确定的,计算sizeof(数组名)计算的是整个数组的大小,结果便是16

printf("%d\n", sizeof(a[3]));
  • 我们来看一下运行结果~~

在这里插入图片描述

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

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

相关文章

机械电子设备信息展示预约小程序的效果如何

电子电工机械设备制造业所涵盖的产品非常广泛,各种产品也都是人们生活所需,近些年来,借势市场规模也在迅速增加中。 电子机械设备产品有大件也有小件,但多数产品都是特定人群购买,因其具有长期使用性,因此…

等级保护建设全流程

等保,全称为信息安全等级保护,是对信息和信息载体按照重要性等级分级进行保护的一种工作。 企业的信息系统有收集、储存用户信息的,都需要进行等保建设,以此来整改提升系统的安全防护能力,降低被攻击的风险。若不然一旦…

Android源码分析 - Service启动流程

作者:dreamgyf 这次我们就来讲讲四大组件之一的Service是如何启动和绑定的 流程图 在查阅资料的过程中,我发现有些博主会将梳理好的流程图贴在开头,我觉得这样有助于从宏观上去理解源码的整个流程和设计理念,所以以后的文章我都…

LeetCode---117双周赛---容斥原理

题目列表 2928. 给小朋友们分糖果 I 2929. 给小朋友们分糖果 II 2930. 重新排列后包含指定子字符串的字符串数目 2931. 购买物品的最大开销 一、给小朋友们分糖果I 看一眼数据范围,如果没有啥其他想法思路就直接暴力,时间复杂度O(n^2) 思路&#x…

@Autowired 注入Mapper接口时报红色下划线警告

问题描述 在使用Autowired 注入Mapper接口时报红色下划线警告,虽然对代码没有什么影响可以正常执行,但是作为代码猿的我看着这个报红的就很不舒服,就想着让他不报红 问题描述: Autowired 自动注入,首先要求被自动注入…

精密云工程:智能激活业务速率 ——华为云11.11联合大促倒计时 仅剩3日

现新客3.96元起,下单有机会抽HUAWEI P60 Art,福利仅限双十一,机会唾手可得,立即行动! 双十一购物节来临倒计时,华为云备上多款增值产品,以最优品质迸发冬日技术热浪,满足行业技术应用…

ROS 学习应用篇(九)ROS中launch文件的实现

launch文件就好比一个封装好的命令库,我们按照在终端中输入的代码指令,全部按照launch语言格式封装在一个launch文件中,这样以后执行的时候,就可以不用开很多终端,一条一条输入代码指令。 lauch文件的语言风格很想我之…

Redis(列表List)

使用LPUSH从头部添加元素,可以一次添加一个或多个。 使用LRANGE 查看列表中的数据,0表示起始位置,-1表示结束位置。 当然也可以使用RPUSH来从尾部添加元素。 可以使用RPOP从尾部删除元素,会返回删除的元素的值。 同理使用LPOP…

【python基础】用户输入和while循环详解

文章目录 一. 函数input()的工作原理1. 编写清晰的程序2. 使用int()来获取数值输入3. 求模运算符 二. while循环简介1. 使用while循环2. 让用户选择何时退出3. 使用标志4. 使用break退出循环5. 在循环中使用continue 三. 使用while循环处理列表和字典1. 在列表之间移动元素2. 删…

HIKVISION iSecure Center RCE 海康威视综合安防管理平台任意文件上传 POCEXP

参考:GitHub - Sweelg/HIKVISION_iSecure_Center-RCE: HIKVISION iSecure Center RCE 海康威视综合安防管理平台任意文件上传 POC&EXP(一键getshell) 速修!海康威视综合安防RCE已被用于勒索 近日,勒索团伙利用海康威视综合安防…

Redis篇---第三篇

系列文章目录 文章目录 系列文章目录前言一、为什么 Redis 需要把所有数据放到内存中?二、Redis 的同步机制了解是什么?三、pipeline 有什么好处,为什么要用 pipeline?前言 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到…

「校园 Pie」 系列活动正式启航,首站走进南方科技大学!

PieCloudDB 社区校园行系列活动「校园 Pie」已正式启动。「校园 Pie」旨在促进数据库领域的学术交流,提供一个平台让学生们了解最新的数据库发展趋势和相关技术应用。 在「校园 Pie」系列活动中,PieCloudDB 社区将携拓数派技术专家,社区大咖…

我们应该如何理解Java集合框架的关键知识点?

我们应该如何理解Java集合框架的关键知识点? java集合是教存取数据的一个容器,涵盖了各种存和取的方式,应用在不同的工作场景中,要想了解java集合的相关知识,建议先好好学习一下数据结构这本书。最近很多小伙伴找我&am…

【2023高交会成绩单出炉】Gooxi斩获“AIC年度标杆应用奖”大奖

第25届中国国际高新技术成果交易会(简称“高交会”)在深圳盛大开幕,作为高交会人工智能板块的重点活动之一,11.16日的第八届人工智能领袖大会的AIC年度奖项评选环节备受关注,Gooxi从多家入围企业中脱颖而出&#xff0c…

【广州华锐互动】VR可视化政务服务为公众提供更直观、形象的政策解读

虚拟现实(VR)技术正在逐渐应用于政务服务领域,为公众提供更加便捷、高效和个性化的服务体验。通过VR眼镜、手机等设备,公众可以在虚拟环境中参观政务服务中心,并根据自己的需求选择不同的办事窗口或事项进行咨询和办理…

【Android】如何使用模拟器调试安卓项目

1、电脑安装逍遥模拟器,用来跑安卓项目。安装好模拟器之后,直接起安卓项目,自动会在选择设备处显示 2、如果前端是安卓后端是其他语言的话,这种前后端分离的模式,需要监听端口,原因是运行安卓和后端编译器都…

【JVM】内存区域划分、类加载机制(双亲委派模型图解)、垃圾回收(可达性分析、分代回收)

一、JVM简介 JVM (Java虚拟机) 是执行Java字节码的虚拟机。它是Java平台的核心,并且为Java代码提供了跨平台的能力。JVM 是一种虚拟的计算机,在其上运行的程序是Java字节码,它提供了Java代码在不同操作系统和硬件平台上执行的能力。JVM 将Ja…

射频与微波综合测试仪-4958手持式微波综合测试仪

4958 微波综合测试仪 频率范围:1MHz~20GHz 4958手持式微波综合测试仪测量频率范围可达1MHz~20GHz,集电缆和天线驻波比测试、不连续点故障定位测试、插入损耗和增益测试、频谱分析、功率测量等多种功能于一体,携带方便&…

Unity中Shader纹理的多级渐远Mipmap

文章目录 前言一、什么是Mipmap二、Mipmap能带来什么好处1、增加缓存命中率,减少像素抖动感2、可配合质量设置来分级加载,减少不同配置下的内存 二、我们在Shader中实现一下该效果1、我们先布置一个简单的棋盘格,用于测试纹理的多级效果2、我…

【论文阅读】2736. 最大和查询-2023.11.17

题目: 2736. 最大和查询 给你两个长度为 n 、下标从 0 开始的整数数组 nums1 和 nums2 ,另给你一个下标从 1 开始的二维数组 queries ,其中 queries[i] [xi, yi] 。 对于第 i 个查询,在所有满足 nums1[j] > xi 且 nums2[j]…