指针的进阶续(笔试题强化练习)
写在前面:在上次我们学习了指针的相关类型的知识,对指针家族的成员基本有了了解,这次让我们跟着一些题目来练习和补充一些知识,这有助于我们强化理解这些知识。
话不多说,我们马上开始:
1.指针和数组的笔试题解析
1.1一维数组
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));
先来给出输出结果:

这里我们来挑些易错的进行分析和讲解:
1.sizeof(a):这个不用多说,我们都知道一维数组的数组名表示首地址,但是前面我们了解到了有两个特殊的情况,一种是sizeof(数组名)的时候表示的是整个数组中的所有元素所占的总字节数,还有一种就是&(数组名)的时候,取出的是整个数组的地址,虽然和数组首元素地址相同,但是它加1跳过的是一整个数组的长度,而普通的数组名加1只是跳到数组的下一个元素而已;
2.sizeof(a+0):这个和sizeof(a)不是一样的......吗?稍等,你要是这么认为你就错了,让我们来慢慢分析,首先,我们应该知道sizeof这个函数的一些原理,sizeof计算的是括号内所占的内存的空间的大小,单位是字节,不关注内存中到底存放的是什么,sizeof是操作符,并不是函数,
我们说,sizeof内部只有单独放一个数组名的时候才表示数组首元素的地址,但是它现在加了0,所以就变成了数组首元素的地址加了0,其结果导致其变成了地址的运算,也就间接导致了sizeof认为现在在他要算的其实就是一个指针变量而已,并不是一个数组,所以,sizeof会返回数字4(x86,32位环境下)或者是(x64,64位环境下);
3.sizeof(*a): 首先我们来看,该括号里面既不是只有数组名,也不是取地址数组名,所以,括号里的a就表示数组首元素的地址,对其解引用,就得到a[0]的值,也就是四个字节的int型 ;
4.sizeof(a+1):同上原理,现在a表示的是数组首元素的地址,所以我们的加1操作就是得到了第二个元素的地址,所以返回值为指针大小(4或8);
5.szieof(&a):现在有了取地址数组名,所以我们现在&a表示的是整个数组的地址,但是sizeof计算的仍然是指针大小,即4或8;
6.sizeof(*&a):我们规定,解引用操作与取地址操作可以相互抵消,所以返回的相当于sizeof(a);
7.sizeof(&a+1):整个数组的地址加1,将会跳过一个数组的字节数的步长,现在的指针指向的是a数组的最后一个元素的末尾,但是其本身还是地址,所以其返回值仍然为指针的大小;
1.2 字符数组
什么?你说上面的题没难住你?那接下来就会更难些了,准备好我们就出发吧......
温馨提示:这边由于c和c++存在不兼容问题,导致strlen函数在cpp文件运行时会出现问题,我这边用.c文件进行编译运行
//1.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));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));//2. 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));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));//3. 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));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));
首先,我们来看一下sizeof和strlen有什么不同
1.sizeof计算占用内存空间的大小,单位是字节,不关注内存中到底放的是什么,也不会对内存中的表达式进行求值;
2.sizeof是操作符,strlen是函数;
3.strlen是针对字符串的,本质上是求出在'\0'之前出现的字符的个数。
1.2.1 第一部分
运行结果:

我们来分析一下:
首先,字符数组和字符串的区别:有无’\0',这个比较重要,对于sizeof来说,不管有无'\0'它都会正确的计算字节数并返回,对于strlen来说,没有'\0',相当于字符串没有终止标志,得到的可能就是一个随机值。
1.sizeof(arr + 0):我们说sizeof括号内部只有单独放着数组名或者&(数组名)的时候不一样,那么现在加了0,会不会相当于没加呢?不如这样,我们来调试一个就知道了,

上面的调试显示出了arr和arr+0明显是两个不同的变量,arr+0表示的是第一个元素的地址,arr则表示的是整个数组,所以sizeof(arr)就是返回int*的大小,4或8;
2.sizeof(*arr):此时arr表示的由整个数组的范围缩减到了数组首元素的地址,*a=*(&a[0])=a[0],所以返回char类型的大小1;
3.sizeof(&arr),相当于整个数组的地址,但是其本质上还是指针,所以大小固定为4或8个字节;
4.sizeof(&arr+1):这个&arr+1其实是指向了非法内存arr末尾元素的下一个地址,但是sizeof不会管那么多
5.sizeof(&arr[0]+1):这个无可厚非,表示的是第二个元素的地址,4或8个字节
6.strlen(arr):此处arr为字符数组,意味不知道终止符'\0'的位置,所以该返回值为随机值
7.strlen(arr+0):此处相当于将arr[0]传入strlen,返回值和strlen(arr)一样为随机值
8.strlen(*arr):*arr=*(&arr[0])=a[0]='a'=97,strlen会将97作为地址进行寻找,形成非法访问操作,
9.strlen(&arr):也为随机值,&arr拿到的就是整个数组的地址,也是从arr[0]开始数,所以拿到的随机值应和6,7保持一致
10.strlen(&arr+1):随机值,与前面的随机数长度差6(一个字符数组的长度)
11.strlen(&arr[0]+1):随机值,与6,7,9中的随机值相差1,

1.2.2 第二部分
运行结果:

几点需要注意:
1.sizeof(arr)会计算'\0'字符;
2.sizeof(arr+0)表示的是&arr[0];
3.sizeof(*arr)表示的是sizeof(arr[0]);
4.&arr,&arr+1,&arr[0]+1分别为整个字符串的地址,监视窗口如下:

注意此时&arr+1是跳过了'\0',直接取到了'\0'的后面的位置(可以由两处起始地址的差值来求)
5.strlen不和sizeof一样,没有arr和arr+0的区分,对于strlen都一样
6.strlen(&arr)=strlen(arr),不建议使用
7.strlen(&arr+1):指向了字符串的'\0'的后面,返回随机值;
8.strlen(&arr[0]+1)=strlen(&arr[1])=6-1=5;
1.2.3 第三部分
输出结果:

1.p中存储的是字符串首元素的地址,p=&'a';
2.p+1为字符'b'的地址
3.&p,&p+1均与原字符串无关

4.&p[0]+1=&'a'+1=&'b';
1.3 二维数组
关于指针的问题,最抽象和难理解的也就是二维数组的相关操作了吧,不要着急,我们来边看题目边分析,
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]));
首先是输出结果:

首先对于以上的二维数组,我们平时做题通常认为它是这样的:

而实际上,它真正在内存中的存储是这样的:

这一点还希望大家知晓,接着我们来看题目:
1.sizeof(a[0]):由于是二维数组组,所以说a[0]表示的是第一行的一维数组,问题也就转化为了第一行的数组的数组名,也就是求第一行数组所占的字节数(4*4=16);
2.sizeof(a[0] + 1):有的读者是不是认为a[0]+1相当于a[1]啊?敲黑板了,重点来了,我告诉你并不是,由于我们的a[0]不是单独放在sizeof内部,还加上了1,导致其所代表的的指针的地址范围“缩小”或者“降级”(该名词仅为笔者叙述词,不具有实际意义,不要深挖),也就是说,原来a[0]代表的是第一行的地址,而现在a[0]就变成了普通的第一行的首元素的地址,即&a[0][0],再加上1,就变成了&a[0][1],其大小为4或8个字节。
3.sizeof(*(a[0] + 1)):同2,a[0]此处代表a[0][0],加1位&a[0][1],再解引用,所以括号内表示a[0][1],也就是4个字节;
4.sizeof(a + 1):a并未单独放在sizeof内部,所以a表示二维数组首元素的地址(&a[0]),所以a+1=&a[1],注意二维数组的首元素是第一行的整行,并不是a[0][0]这一个元素,这里的a就是第一行的地址,其类型是int (*)[4](数组指针),是一行为整形的4个数据组成的数组的指针,a+1就相当于跳过了第一行,所以其结果仍然为一个指针的大小4或8;
5.sizeof(*(a + 1)):a没有单独存在,所以a会“降一级”变为数组首元素的地址&a[0],再加1,则表示&a[1],再解引用,就得到第二行数组,返回的就是第二行数组的字节数16;第二种就是*(a+1)可直接表示为a[1],也正确;
6.sizeof(&a[0] + 1):由上面的分析得出其表示第二行的地址,返回值为一个指针大小;
7.sizeof(*(&a[0] + 1)):&a[0]+1=&a[1],*&a[1]=a[1],所以返回值为16;
8.sizeof(*a):此时数组名变成首元素的地址,二维数组首元素的地址为第一行一维数组的地址,也即*a=*(&a[0])=a[0],返回的就是第一行的所有元素的字节数16;
9.sizeof(a[3]):“xd,你题目写错了吧,a[3][4]的二维数组,行数只能为0-2,你这写个3,这不明摆的坑我们吗?”,稍等,不放你可以先去上面看看运行结果,显示是能运行的,这就奇怪了,sizeof这个操作符吧,他比较懒,不会跟你计较越不越界,sizeof在程序编译期间就会处理,其返回值至于内部数据的类型有关,并不会参与内部的运算,这样就不会需要内部运算了,sizeof就会根据原来的数组结构进行推断(哎~原来的数组一行有四个int,那我的第四行应该也是四个int吧?哎,不管了,就当四个int返回吧,我累了~~~)也就检测不出越界访问了,我们来看个例子

从上面看出b并没有返回我们认为的int型,而是继续保持原来的数据,同样间接证明了a+2没有进行。
下面是二维数组的运行时相关数组内容监视窗口(增添数据以观测不同点):

2.指针的笔试题
下面就是一些精华的应用场景了,准备好了我们就发车吧~~~
2.1
int main()
{int a[5] = { 1, 2, 3, 4, 5 };int *ptr = (int *)(&a + 1);printf( "%d,%d", *(a + 1), *(ptr - 1));return 0;
}
//程序的结果是什么?

你做对了没?
解析:&a+1表示整个元素的地址,再向后移动一位处的地址,将其减去一正好是数组的最后一个元素,而*(a+1)表示a[1];
2.2
struct Test
{int Num;char *pcName;short sDate;char cha[2];short sBa[4];
}*p;
//假设p 的值为0x100000。 如下表表达式的值分别为多少?
//已知,结构体Test类型的变量大小是20个字节
int main()
{p=(struct Test*)0x100000;printf("%p\n", p + 0x1);printf("%p\n", (unsigned long)p + 0x1);printf("%p\n", (unsigned int*)p + 0x1);return 0;
输出结果如下:

其中的0x1其实就是十六进制数字的1,相当于p+1的作用,那么p+1要加上二十个字节的长度,也就是p+1=0x100014,第二个将p强制类型转换为了一个unsigned long型的整形数据,所以加1就变成了真正意义要上的加1,也就是相当于0x100001,再看最后一个,将本来大小为20个字节的指针强制类型转换成了4个字节大小的指针,所以加1就会跳过四个字节,即0x100004;
2.3
int main()
{int a[4] = { 1, 2, 3, 4 };int *ptr1 = (int *)(&a + 1);int *ptr2 = (int *)((int)a + 1);printf( "%x,%x", ptr1[-1], *ptr2);return 0;
}
输出结果:(基于小端的x86环境下)

此处的ptr[-1]可以看成是*(ptr-1),就相当于ptr的地址减1,也就是指向了4这个元素,第二个是比较难理解的,我们不妨先来看一看他们代表的内存都是啥吧

从上面我们可以得出,ptr的地址只是比a[0]的地址多了1, 这就涉及到了字节偏移的问题,我们的ptr2比a[0]多1的话,相当于它指向a[0]的末尾,又由于小端存储,所以低地址上方低位字节,又因为ptr2为int*,会自动向后寻找四个字节:

2.4
#include <stdio.h>
int main()
{int a[3][2] = { (0, 1), (2, 3), (4, 5) };int *p;p = a[0];printf( "%d", p[0]);return 0;
}
其输出结果为1,
首先,关于逗号表达式,其最终返回值就是最后的那条语句,数组里面真正存储的是1,3,5三个数字,剩下的就都默认初始化为0了;
2.5
int main()
{int a[5][5];int(*p)[4];p = a;printf( "%p,%d\n", &p[4][2] - &a[4][2], &p[4][2] - &a[4][2]);return 0;
}
注意,还是要用.c文件编译,c++规定比c多

上来我们就注意到两个数组大小不同,其实如果非要这样运行的话,我们可以这样想:

可见,要求的结果地址相差4个字节,结果为-4,但是作为地址不会管你整数还是负数,它会直接把-4转换为地址来打印。
2.6
#include <stdio.h>
int main()
{char *a[] = {"work","at","alibaba"};char**pa = a;pa++;printf("%s\n", *pa);return 0;
}
输出结果:
at
解析:a的每个数组元素是char*,也就是a的每个数组元素表示的是字符串的地址,而pa的类型为char**,也就是说pa指向的是a数组,如下图

而我们又知道,当有int *p时,p+1表示的是p的地址向后移动4个字节,所以char**pa的时候,pa++就相当于pa向后移动了char*个字节,如下图

2.7
int main()
{char *c[] = {"ENTER","NEW","POINT","FIRST"};char**cp[] = {c+3,c+2,c+1,c};char***cpp = cp;printf("%s\n", **++cpp);printf("%s\n", *--*++cpp+3);printf("%s\n", *cpp[-2]+3);printf("%s\n", cpp[-1][-1]+1);return 0;
}
输出结果:还是.c文件吧,你懂得

解析:这后面的提酒相对较难一些了,需要仔细分析,还会有很多的坑,话不多说,先画个图

一目了然~~~呃~~~我们再看看吧
这样只能解决第一个问题,从第二个问题开始,我们就要考虑符号优先级问题了,我们有前后置++大与+,解引用*也大于+,所以对与第二个式子我们的运算顺序为:(*--(*++cpp))+3,最后我们计算可得出,结果为第一个字符串的第四个字符往后(注意此时的cpp在第一步中已经指向了c+2;同理第三个也可以变成*(*(cpp-1)-1)+1,也可得出结果,重点是要熟悉数组和指针的相互转换关系。
一件不幸的事,我的笔记本要没电了,所以就先到这吧,需要更新我会尽快补上的~~~
相关文章:
指针的进阶续(笔试题强化练习)
写在前面:在上次我们学习了指针的相关类型的知识,对指针家族的成员基本有了了解,这次让我们跟着一些题目来练习和补充一些知识,这有助于我们强化理解这些知识。 话不多说,我们马上开始: 1.指针和数组的笔…...
一个供参考的计算机的学习路线
本文是介绍如何成为一个Geek,一个真正的计算机高手。 适合有成为IT领域技术大牛的人参考。 写给大一新生和所有向深耕IT领域的人,避免走一些弯路。 仅代表个人想法,供批判性参考。 第一门入门的必备功课-语法与算法 什么是计算机?…...
React(五):受控组件、高阶组件、Portals、Fragment、CSS的编写方式
React(五)一、受控组件1.什么是受控组件(v-model)2.收集表单数据:input和单选框3.收集表单数据:下拉框二、非受控组件三、高阶组件1.什么是高阶组件2.高阶组件的应用13.高阶组件的应用2-注入Context4.高阶组件的应用3-登录鉴权5.高…...
MATLAB——系统环境
MATLAB概述MATLAB的发展MATLAB:MATrix LABoratory1980年前后,Cleve Moler教授编写的Linpack 和Eispack的接口程序。1984年,MATLAB第1版(DOS版)1992年,MATLAB4.0版1994年,MATLAB 4.2版1997年,MATLAB 5.0版1999年&#x…...
2 GateWay工作流程+GateWay搭建
GateWay工作流程GateWay搭建 核心流程图如下: 核心概念: 客户端向 Spring Cloud Gateway 发出请求。如果Gateway Handler Mapping确定请求与路由匹配,则将其发送到Gateway Web Handler 处理程序。此处理程序通过特定于请求的Fliter链运行请求…...
【微信小程序】富文本rich-text的图片预览效果的几种方法
前言 使用原生小程序开发,实现在富文本rich-text中的图片预览效果的几种方法对比。 1.正则wx.previewImage(有明显不足) 一个不需要用额外组件或插件的方法: 思路:使用正则把图片的url进行剖离出来,push…...
通信网络-Socket、Java中的网络支持、多线程服务器
前言 通信网络-Socket、Java中的网络支持、多线程服务器 场景:使用java网络创建一个聊天室 博客地址:芒果橙的个人博客 文章目录前言通信网络-SocketTCP/IPTCP/IP 模型端口Java中的网络支持概念1. InetAddress2. URL3. Socket4. Datagram多线程服务器应用…...
搞懂 JS this、call、apply、bind
搞懂 JS this、call、apply、bind javascript 的 this ECMAScript 规范中这样写: this 关键字执行为当前执行环境的 ThisBinding。 MDN 上这样写: In most cases, the value of this is determined by how a function is called. 在绝大多数情况下&…...
力扣209长度最小的子数组
209. 长度最小的子数组 给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其和 ≥ target 的长度最小的 连续子数组 [numsl, numsl1, …, numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1…...
【mysql是怎样运行的】-InnoDB数据页结构
文章目录1. 数据库的存储结构:页1.1 磁盘与内存交互基本单位:页1.2 页结构概述1.3 页的上层结构2. 页的内部结构2.1 第1部分:文件头部和文件尾部2.1.1 File Header(文件头部)(38字节)2.1.2 File…...
VIM实用指南(10)语法自动补全插件coc.nvim
最近发现了一个新的自动补全插件coc.nvim异步,nodejs后端,配合它自身的lsp支持用起来非常舒服,同样也支持lsp和snippets,强烈推荐,值得一试。 1、使用vimplug安装插件 1.进入coc.nvim 在github的主页https://github.…...
【Vue3 第二十二章】过渡动画
一、基本用法 <Transition> 是一个内置组件,这意味着它在任意别的组件中都可以被使用,无需注册。它可以将进入和离开动画应用到通过默认插槽传递给它的元素或组件上。进入或离开可以由以下的条件之一触发: 由 v-if 所触发的切换由 v-…...
【linux】:进程状态(僵尸进程等)以及环境变量
文章目录 前言一.进程状态 进程的优先级二.环境变量总结前言 本篇文章是接着上一篇【linux】:进程概念的后续,对于有基础的同学可以直接看这篇文章,对于初学者来说强烈建议大家从上一篇的概念开始看起,上一篇主要解释了冯诺依曼体系以及操…...
【C语言——练习题】指针,你真的学会了吗?
✨✨✨✨如果文章对你有帮助记得点赞收藏关注哦!!✨✨✨✨ 文章目录✨✨✨✨如果文章对你有帮助记得点赞收藏关注哦!!✨✨✨✨一维数组练习题:字符数组练习题:字符指针练习题:二维数组练习题&am…...
Linux用户空间与内核空间通信(Netlink通信机制)
一,什么是Netlink通信机制 Netlink是linux提供的用于内核和用户态进程之间的通信方式。但是注意虽然Netlink主要用于用户空间和内核空间的通信,但是也能用于用户空间的两个进程通信。只是进程间通信有其他很多方式,一般不用Netlink。除非需要…...
3.3日报
今天写技术文档 跟需求对其 找负责人要上游数据接口,并处理更新时间问题 遇到的问题: 1.调用上游接口,需要token,而我的数据看板是不需要登录的,需要其他途径获取token 不同数据使用的接口不在一个项目中ÿ…...
并发编程-进程
并发编程-进程 进程创建启动 python提供了multiprocessing模块来支持多进程 multiprocessing.Process(targettask, args(arg,))用于创建进程 Process类相关方法 start() 启动进程join() 等待进程结束 启动子线程 【注意】线程启动代码块要放在__name__ __main__下 方式…...
LeetCode196_196. 删除重复的电子邮箱
LeetCode196_196. 删除重复的电子邮箱 一、描述 SQL架构 Create table If Not Exists Person (Id int, Email varchar(255)) Truncate table Person insert into Person (id, email) values (1, johnexample.com) insert into Person (id, email) values (2, bobexample.com…...
Auto.js Pro 替代品
Time : 2023年3月2日04:20:31 Mode : 持续更新中,排名不分先后.想起啥写啥 By : MemoryErHero NewTime: 2023年3月4日12:11:49 NO13. Autox.js文档: http://doc.autoxjs.com/ NO14. AutoJs6项目文档:https://github.com/SuperMonster003/AutoJs6 NO…...
红日(vulnstack)2 内网渗透ATTCK实战
环境配置 链接:百度网盘 请输入提取码 提取码:wmsi 攻击机:kali2022.03 web 192.168.111.80 10.10.10.80 自定义网卡8,自定义网卡18 PC 192.168.111.201 10.10.10.201 自定义网卡8,自定义网卡18 DC 192.168.52.1…...
TDengine 快速体验(Docker 镜像方式)
简介 TDengine 可以通过安装包、Docker 镜像 及云服务快速体验 TDengine 的功能,本节首先介绍如何通过 Docker 快速体验 TDengine,然后介绍如何在 Docker 环境下体验 TDengine 的写入和查询功能。如果你不熟悉 Docker,请使用 安装包的方式快…...
基于服务器使用 apt 安装、配置 Nginx
🧾 一、查看可安装的 Nginx 版本 首先,你可以运行以下命令查看可用版本: apt-cache madison nginx-core输出示例: nginx-core | 1.18.0-6ubuntu14.6 | http://archive.ubuntu.com/ubuntu focal-updates/main amd64 Packages ng…...
linux arm系统烧录
1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 (忘了有没有这步了 估计有) 刷机程序 和 镜像 就不提供了。要刷的时…...
土地利用/土地覆盖遥感解译与基于CLUE模型未来变化情景预测;从基础到高级,涵盖ArcGIS数据处理、ENVI遥感解译与CLUE模型情景模拟等
🔍 土地利用/土地覆盖数据是生态、环境和气象等诸多领域模型的关键输入参数。通过遥感影像解译技术,可以精准获取历史或当前任何一个区域的土地利用/土地覆盖情况。这些数据不仅能够用于评估区域生态环境的变化趋势,还能有效评价重大生态工程…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
Caliper 配置文件解析:config.yaml
Caliper 是一个区块链性能基准测试工具,用于评估不同区块链平台的性能。下面我将详细解释你提供的 fisco-bcos.json 文件结构,并说明它与 config.yaml 文件的关系。 fisco-bcos.json 文件解析 这个文件是针对 FISCO-BCOS 区块链网络的 Caliper 配置文件,主要包含以下几个部…...
网络编程(UDP编程)
思维导图 UDP基础编程(单播) 1.流程图 服务器:短信的接收方 创建套接字 (socket)-----------------------------------------》有手机指定网络信息-----------------------------------------------》有号码绑定套接字 (bind)--------------…...
Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决
Spring Cloud Gateway 中自定义验证码接口返回 404 的排查与解决 问题背景 在一个基于 Spring Cloud Gateway WebFlux 构建的微服务项目中,新增了一个本地验证码接口 /code,使用函数式路由(RouterFunction)和 Hutool 的 Circle…...
用机器学习破解新能源领域的“弃风”难题
音乐发烧友深有体会,玩音乐的本质就是玩电网。火电声音偏暖,水电偏冷,风电偏空旷。至于太阳能发的电,则略显朦胧和单薄。 不知你是否有感觉,近两年家里的音响声音越来越冷,听起来越来越单薄? —…...
