图解 | 你管这破玩意儿叫指针?

C语言(三)图解: 一级指针 和 二级指针, 数组 和 指针, 指针数组, 数组指针, 数组指针数组 以下是我学习一级指针和二级指针,数组和指针,指针数组,数组指针,数组指针数组的总结,画图更容易理解: ①一级指针: 是指针,该指针指向一块内存,该指针变量存放的就是这块内存的地址,这样说不直观,用图解释会简单明了: 图解一级指针: ②二级指针: 是指针,该指针指向一个一级指针,该二级指针变量存放的就是一级指针的地址,这样说不直观,用图解释会简单明了: 图解二级指针: ③指针和数组 指针... 阅读详情

本系列分三篇,用破玩意的方式彻底理解好指针的本质:

  • 你管这破玩意叫指针 -- 基础篇

  • 你管这破玩意叫指针 -- 进阶篇

  • 你管这破玩意叫指针 -- 变态篇

话不多说,开始!

内存,通常被严谨地画成下面这个样子,一个下方是低地址上方是高地址的格子楼。

64d820c721ce4c8fd99c5453053b40d5.png

但我今天换种画法,画成下面这个样子。

9b18249fa4f484e80f9082c4186446ff.png

每个格子代表内存中的 1 个字节(8 位),格子上的数字就代表内存地址,我也直接用 10 进制来表示了,免得 16 进制又算不明白了。

目前内存是完全空的,格子里没有任何内容。

试想一下,如果你忘掉所有的语法规则和编程规范,你会如何描述对这些内存格子的操作呢?

一、类型系统

很简单,往格子 3 处放个数字 29,往格子 6 处放个数字 38,就这么简单直接地描述即可。

a4636e964357bdcec328b7638a4f0d53.png

但是这样说话太麻烦了,什么往格子 3 处放个数字 29 的,废话太多,也不方便不讲感情的计算机去理解。

那我们就定个指令,使用 mov $x, (y) 表示把数字 x 放入格子 y,如下:

mov $29, (3)
mov $38, (6)

这就表示刚刚说的:

把数字 29 放入内存格子 3
把数字 38 放入内存格子 6

是不是太简单了?别急,好戏马上开始!

如果要把数字 999 放入内存格子 8,该怎么办呢?

由于 1 个格子表示 1 个字节,只有 8 位,因此只能表示 256 个数字,要么是有符号的 -128 ~ 127,要么是无符号的 0 ~255,显然数字 999 无法放在 1 个格子内,只能占用 2 个格子了。

那也好办,就这么说,把数字 999 放入格子 8,连续占用两个格子。

c7173b7ac80c4fc690c22e0bc9b97da6.png

但这样,我们刚刚的 mov 指令就得改改了,不但要表示"存放"这个含义,还得表示占用了多少个格子。

我们用 movb 表示只占 1 个字节,用 movw 表示占用 2 个字节。那么,刚刚的三个数字,就分别可以这样用指令来表示了:

movb $29, (3)
movb $38, (6)
movw $999, (8)

含义就是:

把数字 29 放入内存格子 3,占 1 个字节
把数字 38 放入内存格子 6,占 1 个字节
把数字 999 放入内存格子 8,占 2 个字节

OK,既然有了 1 字节和 2 字节的的指令,不妨再设计下,用 movl 表示 4 字节,movq 表示 8 字节 ...

movb 占用 1 字节
movw 占用 2 字节
movl 占用 4 字节
movq 占用 8 字节

不知不觉,类型系统就被你悄悄设计出来了!当然,虽然这只是个半成品。

二、变量

你不断地往不同格子里放数据。

比如我把我的年龄放在 11 号格子(占 1 字节),把我的月薪放在 14 号格子(占 4 字节)。

fdc6db8f35b89191474804d948ec6d80.png

现在我们的内存已经非常混乱了,你根本记不住原来的 3 号格子放的数据表示什么,11 号格子又表示什么,只能通过看数字知道 14 号格子里放的确实是我的月薪。这该怎么办呢?

增加一层抽象嘛!我们给这些放了我们数据的格子,都贴上个标签,就可以不用再记那些无意义的格子编号了。

b84d1bbab3beb54066750662429cc732.png

这样以来,其实我们也不再关心,这些标签到底在哪个格子里,只要给我找到格子把我的数据放进去就可以了。

movb $29, a
movb $38, b
movw $999, c
movb $18, age
movl $2147483647, salary

当然,我还需要再通过这个标签,把我刚刚放进去的数据找出来。

这很简单,但存在一个问题,放进去的时候,我们可以通过 movb,movw,movl 等知道占用多少个格子。而取出来的时候,标签上可没有写这个数据占用了多少个格子,这是有问题的。

因此,在定义这个标签时,不能光取个名字,还需要有个信息就是,这个标签对应的数据,占了多少个格子。

我们就效仿刚刚的存放操作,也规定一系列单词,来修饰这些标签,表示占用了多少个格子。

char 表示 1 个字节,short 表示 2 个字节,int 表示 4 个字节,long 表示 8 个字节 ...

9a4de5147f5a9bd83bf0347c82e70209.png

于是乎刚刚的 5 个数据,就可以表示为如下指令:

char a = 29;
char b = 38;
short c = 999;
char age = 18;
int salary = 2147483647;

行了,我也别藏着掖着了,相信大家也知道,这里就是 C 语言的写法,而刚刚那堆 mov 是汇编语言的写法。

这些 char a,char b,int salary 等,就是变量!记住,变量不但要有名字,还得有类型!

三、变量定义与赋值

其实,刚刚的写法,是把变量的定义与赋值操作写在一行了。

比如有如下语句:

int a = 1;

实际上是分成两步的:

// 变量的定义
int a;
// 变量的赋值(此处也可以叫变量的初始化)
a = 1;

其中变量的定义是为了方便程序员后面去用它,这部分不是给 CPU 看的。

7928789667391a89a04c2bde597fa1b5.png

而变量的赋值才是真正在内存中把数据放进去,这部分才真正涉及 CPU 具体指令的执行。

49b98ca2347dfca93ebad2e63c841249.png

也就是说,如果你仅仅定义了一个变量 int a; 但是没有给它初始化的赋值操作,那么最终在 CPU 执行指令的时候,这个定义根本就没有任何体现。

四、指针

现在,让我们把内存清空,回到一开始的那一片净土上。

ffebdd28bf4c30d82753c7dbaa7268db.png

我们来搞点花样。我将我的密码(1234)存储在一个 short a 中,假设这个变量 a 被放在了 6 号格子处。

c630132d6751cc7e1adbacb33097bb8d.png

同时,我将这个变量 a 的地址,也就是 6 这个数字,存储在另一个变量 int p 中,假设这个变量 p 被放在了 1 号格子处。

f763cc4a30d245e10888c0a3999961e9.png

这样,我寻找我密码的方式,就是先通过 p 所在的内存地址找到里面存的值,也就是 a 的内存地址 6,再通过 a 的内存地址找到里面存的值,也就是我要找的密码 1234。

我们可以用下面的代码来表示刚刚的存放逻辑。

short a = 1234;
// 假设 a 被放在了 6 号格子处
int p = 6;

这里的 p 和 a 都是变量,只不过,p 这个变量有点特殊,它里面存放的值是一个内存地址,我们把 p 这个变量形象地成为指针变量,简称指针。

不过,这样有几个问题,我一个个来说。

1. 取地址

首先,我们在编码阶段,无法知道也无需知道变量 a 会存放在哪里,不然就失去了标签的含义,又回到了需要关心具体的内存地址(也就是格子编号)的时代了。

所以,我们应该有个方法,来在编码阶段表示变量 a 的地址的含义,姑且就叫做 &a 吧。

那么我们的代码,就可以优化为:

short a = 1234;
// 假设 a 的地址是 6
// 那么下面的 p 就等于 6
int p = &a;

用图来表示就是:

8a1f38dea7edd260e919c3646447f188.png

2. 指针变量本身的大小

视角放到这个变量 p 身上,虽然本质上这个变量 p 里面存放的就是一个数值,假设是 6,但是它却表示了一个内存地址的值。

如果让程序员随便规定这个变量 p 的数据类型(也就是占多少个字节),那显然容易出问题。

比如内存地址是 999,那么我用一个 char 类型的变量 p 来存放它,就会有问题。

我们在编码阶段是无法确定一个变量的内存地址是多少的,所以用什么类型的变量来存放它,也是无法判断的。

所以,最稳妥的办法就是,用一个完全能容纳所有内存地址范围的变量类型来存放指针变量。

我们姑且认为我们是在一个 32 位的系统上,那么用一个 4 字节大小的变量来存放,就可以了。(当然,实际上这取决于你的编译器的位数)

现在,我们的指针变量所占用的内存大小,就是固定的 4 个字节,也就是 4 个格子。

程序员无需也无法修改这个大小,那么我们就可以把 p 前面的数据类型去掉了。

short a = 1234;
p = &a;

3. 指针变量的类型

刚刚我们解决了指针变量本身所占用的内存大小,但是还有一个问题没有解决,就是指针变量里存放的内存地址处的变量的大小。

也就是说,上面的指针变量 p 里虽然存放了变量 a 的内存地址 6,但是指针变量 p 却没有任何信息,来说明内存地址 6 处的变量,它的大小是多少。

假如,我们认为内存地址 6 处的变量是个 char 类型,也就是只占用了一个字节,那么显然,会取出一个不符合预期的值。

04ad79b5a8294a40028e6c12d5e29a13.png

当然,如果认为 6 处的变量是个 int 类型,占 4 个字节,虽然数值上可能没有问题,但从某种程度上讲也是不太符合预期的(假如 8 号和 9 号格子里有其他内容,那就更不符合预期了)。

25204d3a16f5a03bf317bc1538459231.png

所以,必须得完全按照变量本身的类型,也就是 short 类型来读取此内存地址处的值,才是正确的。

那我们应该如何表示这个信息呢?即如何表示,变量 p 是一个指针,且这个指针里面存放的内存地址处的变量的类型是 short。

很好办,直接说答案吧。

short a = 1234;
short * p = &a;

p 前面的 * 表示变量 p 是一个指针类型,再前面的 short 表示该指针指向的内存地址处的变量,是个 short 类型的变量。

当然,更准确的说法是,指针 p 将会按照 short 类型的变量来读取它指向的内存,至于那里到底是什么,无所谓。

2892dd8621b2f5a11ccf92857c1a2e60.png

注意哦,这个 short 并不是表示指针变量本身的大小占 2 个字节,指针变量本身我们前面说过了,就是固定的 4 字节大小。

不过总是这样说太绕口了,今后我们就说,变量 p 是个 short * 类型的指针,就可以了。

用上面的图形象地说就是,右边变量 a 蓝色的填充,表示 a 是个 short 类型,而外面的虚线框框,表示指针 p 按照 short 类型的变量来"解读"内存地址 6 处的数值。

两者相匹配了,就是"正确"的编程代码了。

当然,这里的"正确",是说给程序员听的,CPU 才不关心。

4. 指针所指向的值

上面我们已经可以获得某个变量的地址,比如获取 a 的地址就是:

&a

同时我们也可以定义一个指针变量,比如定义一个 short * 类型的指针变量 p:

short * p;

并且,我们通过直接赋值操作,可以给指针变量进行初始化:

p = &a;

当然,上面的代码也可以连起来写,即指针变量 p 的定义与初始化写在同一行:

short * p = &a;

不过,我们还没有一个方法,来表示指针变量 p 所指向的那块内存。

那我们就发明一个,比如想把 p 所指向的那块内存的值改为 999,可以这样写。

*p = 999;

这里的 * 就表示"指向"的含义,即 *p 不是说 p 这个变量的内存地址,而是把 p 这个变量里存的内容当做内存地址来看,指向这个内存地址。

用图表示就是:

910c68f8cd8fe6e040cbd182e4f7d58e.png

所以连起来一个完整的程序就是:

short a = 1234;
// 指针的定义
short * p;
// 指针的初始化,也即指针变量本身的值
p = &a;
// 指针变量所指向的内存地址的值
*p = 999;

执行过后,a 的值会变成 999,或者说 6 号格子与 7 号格子里的值会变成 999。

5. 指针的加减

如果对一个普通变量 +1,比如说:

int a = 1;
int b = a + 1;

那显然,b 的值应该是 2,毫无疑问。

但是如果对一个指针变量 +1,会怎么样呢?

int a = 1;
int *p = &a;
int *p2 = p + 1;

我们假设变量 a 放在了格子 1 处。

变量 a 的值是什么,以及变量 p 被放在了哪里,我们都不关心,就只盯着 p 的值看,显然,一开始的时候是 1。

(为方便演示,下面的图直接表示 p 所指向的内存地址,而不是 p 本身所在的内存地址)

cdd6c2066ae2d38f5e303ebc9d296243.png

我们先不考虑,p + 1 应该是几,如果让你来设计这个语言,你觉得 p + 1 是几比较好呢?

我认为,只有两种较为合理的设计。

第一种,p + 1 就等于 2,就简简单单当做数值进行加法运算而已。

b8dfa27bd8be82c3fab4abff822699dd.png

第二种,p + 1 等于 5,即跨过一个 p 所指向的内存单元的数据类型的大小,也就是 4 字节的 int。

8f1d09cf28ef85588db0a1adaf1334f1.png

你觉得那种比较合理呢?

那显然是第二种嘛!不然和普通变量有啥区别了,你既然设计出了指针变量这个玩意,就需要让它发挥点方便程序员的作用,这才是你设计它的真正目的。

当然你不服,你就想让这个 int * 类型的指针变量,就真真正正在数值上只 +1,也就是让 p 等于 2,该怎么办呢?

很简单,分成三步就好了:

第一步,把 int * 类型的 p 强转为 char * 类型的 p。

b80f7534b1698efdcc17e027525262d8.png

第二步,p + 1。

645e84593408f1f41c7691c82f909ed5.png

第三步,再把 char * 类型的 p 强转为 int * 类型。

8f7ceb9a3fc47d7bf84a135da4c92071.png

完事!用代码表示就是:

p = (int *)((char *)p + 1);

你会看到,C 语言项目中经常使用这样的玩法。

当然,你这一顿花里胡哨的操作,在 CPU 眼里,就是对一个内存地址处的值简简单单地 +1 而已。

五、指针的本质

我们看上面的一张图:

53da2ea0b1f414b9f721e3d086976152.png

其实,别看上面又 short * p 又 short a 的,这是给程序员和编译器看的。

在 CPU 眼里,根本没有这些眼花缭乱的标签,以及五花八门的解读,就是 0 ~ 4 号格子里存了个数字 6,然后 6 ~ 7 号格子里存了个数字 1234,仅此而已。

更进一步讲,其实就只是 1 号格子里存储了数字 6(234 号格子是空的),6 号格子里存储了数字 12,7 号格子里存储了数字 34。

b20a915a4c8fc00aadb8f0961196dac7.png

(当然实际得转换成二进制,再结合大端序还是小端序来看哈,我这里就是简单直观告诉大家 CPU 才不管那么多,就一个格子一个格子的放数字就完事了)

所以,我们经常听书上讲,让大家一定要记住,指针变量中只能存放地址,不要将一个整数或任何其他非地址类型的数据赋给一个指针变量了。

这种说法就非常别扭,很多书上,即想讲清楚指针的本质,又想讲清楚指针的注意事项,混杂在一起,让读者即没有搞清楚指针的本质,又不知道指针的注意事项。

真纠结!

说实话,就光看书而没有经过大量 C 语言的实践,谁能记得住或者理解透彻那些注意事项。而经过大量 C 语言实践的人,指针早就融入进血液中了,谁还来看你讲指针的本质?所以说,这块我觉得非常之矛盾。

实际上,指针变量的本质和普通变量是一样的:

普通变量,写个 short a,是在告诉编译器,当我 a = 1 时,你给我找到一块 2 字节的内存,把 1 填充进去。

指针变量,写个 short * p,是在告诉编译器两件事情:

当我 p = xxx 时,你给我找到一块 4 字节的内存(我们假设指针本身的大小固定 4 字节),把 xxx 填充进去,这就和普通变量完全一样;

当我 *p = yyy 时,你给我找到 xxx 内存地址,并且按照 short 类型也就是 2 字节大小,把 yyy 填充到这里。

38ff098096c97b6297b7f8eb1965b462.png

所以,谁说不能把一个整型变量赋给指针了,我这不就把一个整型变量 xxx 赋给指针 p 了么,我赋值的时候就说它是整型变量了,怎么的吧?

但是我用它的时候,我 *p 又把 xxx 看做是一个内存地址了,就去找内存 xxx 的地方,又怎么的吧?

用代码来表示就是:

我强行把一个整型数值 6 赋值给指针变量 p,然后 *p 去访问内存地址 6 并修改那个地方的值:

int * p = 6;
*p = 999;

我还可以把一个地址值,强行赋值给一个普通变量:

int a = 1;
int b = &a;

这时普通变量 b 里面存储着 a 的地址,我 *b 也同样可以访问到 a 并修改它的值:

*b = 999;

当然如果你真这么写编译器会报错,但没关系,我们可以先把普通变量 b 强转为指针变量,然后再 * 它:

*(int *)b = 999;

你还可以玩些更花哨的,先 & 取地址,再 * 取值,虽然没啥用:

*((int *)*(&p)) = 999;

假如 a 的地址是 6 的话,其实你这些花里胡哨的操作,最后到人家 CPU 眼里,就是一条简单的指令:

movl $999, (6)

就是想把 999 放在 6 号格子嘛!

所以,不要把指针想得多么复杂和神圣,它就是方便了程序员编程,同时告诉编译器应该怎么编译成最终的指令。

你写了个 *p,就是把 p 的值当做内存地址去访问,在汇编语言层面就是加了个括号:

(p)

你写了个 &a,就是取出变量 a 的内存地址,在汇编语言层面就是 lea 指令:

lea a, xxx

你如果写了个 ***p 那就是,相当于加了三次括号:

(((p)))

当然啦,以上都是方便理解的伪指令,具体落实到真正的汇编语言,我会在后续的章节中讲述,直接从汇编语言理解指针,你就会发现指针就是个工具人而已。

六、写在最后

至此,我们的《你管这破玩意叫指针 -- 基础篇》就讲完了。

我们从最开始的内存格子出发,逐渐推导出类型系统和变量的作用,进而再引出本质上和普通变量没有任何区别的指针变量,最后再推导出指针变量相关的操作,带你看清了指针的本质。

1d5a47b3873c2620cd4630fa16a01d76.png

你不要去记本文的知识点,重在整个推导的过程,要去理解指针想解决的问题是什么,它的合理性在哪,哪一部分信息是给程序员和编译器看的,哪一部分操作最终又是真正落实到 CPU 指令的,这些才是关键。

当然,我还是给你简单总结下知识点相关的部分,其实简单说,就这么几件事。

定义一个指针:

int * p;

赋值或初始化一个指针:

p = &a;

修改指针的内容:

*p = 999;

指针的加减(其实到后面讲的数组才有价值):

p = p + 1;

完事,就这些!

最后,给大家推荐两个网站。

一个是可以将 C 语言代码实时编译成汇编代码,你可以用它来自己玩指针做实验,看它最终到 CPU 指令层面是什么样。

https://godbolt.org

21812f2043a83fb551ca84a7145792ab.png

一个是 GNU C 手册,里面对各种语法和作用讲述的非常清楚,不要再用百度搜博客了。

https://www.gnu.org/software/gnu-c-manual/gnu-c-manual.html

比如讲类型系统里的整型类型:

aba3e9c91ad28ff9053271246d0c2e77.png

再比如讲指针的定义和初始化:

5818b43feda5ed359a4285eb7db0410f.png

我相信本文看下来,一定有人想问,short * p 是不是应该写成:

short *p

或者

short* p

自己去上面的文档里找答案即可。

OK,本文到这里就终于要结束了,在接下来的进阶篇里,我会讲述二级指针、数组、函数指针、字符串、结构体、结构体数组与指针等内容。

虽然说是进阶篇,但我认为,指针的本质反而是进阶,而指针的进阶反而是基础。

因为假如理解了上述的一切,下面的所谓指针进阶玩法,都可以通过指针的本质以及语言设计的合理性,推导出来,再往后无非是需要花时间熟练使用和掌握罢了。

所以,理解好今天的内容,非常重要!

(完)

点击下方图片,查看更多精彩

9adc2ab31eef9b82a0304a68116724b4.png

170c7ff5190d7c98882276c081ce191c.png

301d6af4a0044d6aec08a6f8bcba3c3e.png

d224a6c63293d2a550378bc449eae25f.png

0cf01fc35f62a3d79facefbeaf8bdd54.png

C语言二级指针 (清晰易懂 图解概述) 第一篇文,也在不断学习摸索中,如有错误或解释不当,尽请指点 阅读详情

相关推荐

LeetCode 移动零(双指针+图解)

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。 示例: 输入: [0,1,0,3,12] 输出: [1,3,12,0,0] 说明: 必须在原数组上操作,不能拷贝额外的数组。 尽量减少操作次数。 思路分析:使用两个指针,一个指针扫描数组,一个指针用于指向移动好的非零序列的尾端。 图解示例 class Solution { public: ...

hestyle的博客 928

猿创征文丨赶紧进来---看完轻松掌握C语言指针(进阶篇)

耐心看完~对指针不再恐惧..本文详细介绍了指针进阶篇内容: > 指针和数组间的关系:字符指针,, 一维数组和二维数组传参以及一维指针和二维指针传参

记录并分享学习编程时的知识点... 1588

FPGA实战:手把手教你配置4个Aurora 8B/10B IP核共享时钟(附完整工程文件)

本文详细介绍了在Xilinx FPGA上配置四个Aurora 8B/10B IP核并实现时钟共享的实战指南。从工程规划、IP核基础配置到共享逻辑的实现,再到多核时钟域与复位架构的设计,以及时序约束与调试技巧,提供了完整的解决方案和可复用的工程文件。特别强调了GT参考时钟的共享和复位信号的处理,帮助工程师高效解决多通道高速串行通信的设计挑战。

weixin_30879169的博客 416

你管这破玩意叫指针?

你不要去记本文的知识点,重在整个推导的过程,要去理解指针想解决的问题是什么,它的合理性在哪,哪一部分信息是给程序员和编译器看的,哪一部分操作最终又是真正落实到 CPU 指令的,这些才是关键。这样,我寻找我密码的方式,就是先通过 p 所在的内存地址找到里面存的值,也就是 a 的内存地址 6,再通过 a 的内存地址找到里面存的值,也就是我要找的密码 1234。这种说法就非常别扭,很多书上,即想讲清楚指针的本质,又想讲清楚指针的注意事项,混杂在一起,让读者即没有搞清楚指针的本质,又不知道指针的注意事项。

程序员高级码农的博客 1191

双有源桥DC-DC变换器:原理、软开关与移相控制深度解析

隔离型DC-DC变换器是电力电子系统的核心部件,通过高频变压器实现电气隔离与电压匹配,保障系统安全与灵活适配。其工作原理基于功率半导体器件的开关动作,通过调制策略控制能量传输。该技术的核心价值在于实现高效、高功率密度的电能转换,并支持双向能量流动,这对于提升系统整体能效和运行灵活性至关重要。在新能源储能、电动汽车V2G及数据中心供电等场景中,双向能量流成为刚性需求,推动了如双有源桥等先进拓扑的应用。本文聚焦于双有源桥这一实现高效双向隔离变换的“明星”方案,深入剖析其利用移相控制实现软开关的机理。通过分析谐振

weixin_34195142的博客 380

Synopsys Sentaurus TCAD新手教程:从零开始仿真trench MOSFET(附完整代码解析)

本文提供Synopsys Sentaurus TCAD新手教程,详细讲解从零开始仿真trench MOSFET的全过程,包括环境搭建、外延生长、沟槽刻蚀、栅极形成等关键步骤,并附完整代码解析。通过实际案例帮助半导体工程师掌握Sprocess操作技巧,优化工艺参数设置,提升仿真效率。

weixin_30505225的博客 222

指针进阶——看这个就够了

指针

m0_73268549的博客 174

共聚焦显微镜的光源、工作原理与选型

共聚焦显微镜作为科研与工业领域中重要的微观成像工具,凭借光源的精准适配性、光学切片技术的三维成像能力,以及对不同工业场景的定制化适配潜力,为半导体检测、工业部件分析、智能制造升级提供了关键技术支撑。深入理解其光源特性、工作原理与选型逻辑,能帮助工程师与技术人员精准匹配设备与生产需求,既保障微观检测的精度与效率,又为产业优化、技术创新筑牢微观观测的基础。

PhotonixBay的博客 1540

指针进阶版☞(超easy~)

指针详解,来看看吧(^U^)ノ~YO (●'◡'●)

pingwenqi的博客 941

Arcgis模型构建器01——写一个简单的模型

在使用模型构建器解决这个需求之前,我们要想清楚如果我们手动解决的话,应该如何去处理,因为构建模型的过程正是基于我们手动处理的过程来构建的。我有一个全国的dem影像数据和一个陕西省边界范围矢量,现在我想获取陕西省的dem影像的坡度数据。填写完之后点击确定,我们发现,两个输入数据和工具连接起来了,并且通过裁剪工具得到一个中间结果,即。我们发现工具框和中间数据框都存在阴影,说明已经运行过了这个模型,不报错就说明模型运行成功!现在我们就把数据和工具都串联起来了,成功构建好了模型。

爱吃雪糕的小布丁的博客 921

微信小程序:使用mqtt手机屏幕锁屏后导致中断问题,让mqtt在手机黑屏后依然能保持连接及持续后台运行接收或处理任务,详解微信小程序MQTT在应用退到后台或手机熄屏的情况下自动检测并重连【强制保活】

微信小程序切后台后MQTT连接无法维持,微信小程序MQTT一旦用户锁屏、切换到后台或手机熄屏,连接就会断开,导致无法继续监听和处理业务消息,微信小程序mqtt保活方案,微信小程序屏幕锁屏或息屏导致mqtt连接中断怎么办,如何解决MQTT不能黑屏持续连接的问题,微信小程序应用退到后台 MQTT连接断开问题解决,苹果ios手机,安卓手机,uniapp微信小程序mqtt断开怎么解决,后台应用怎么保活,uni-app中MQTT连接频繁断开如何解决?应用退到后台后MQTT连接断开以及常连接断连的问题,微信小程序、MQ

✅ 精选推荐文章 3026

指针进阶(详细)-----C语言

指针就是地址,口语中说的指针通常指的是指针变量。

btkka的博客 361

电气:蒙特卡洛1000个风光场景并通过削减法|聚类法得到几个典型场景(matlab\python实现)

    个人电气目录传送门:学好电气全靠它,个人电气博文目录(持续更新中…)     本文内容包括22页(代码和一些自己对风光的观点) 提示:专栏解锁后,可以查看该专栏所有文章,划算。 文章目录一、理论依据1.风电DG出力概率模型1.2光伏DG出力概率模型1.3对风光的认识二、蒙特卡洛模拟1000个风光场景、并通过削减法得到5个典型风电场景 (Matlab 版程序)三、蒙特卡洛模拟1000个风光场景、并通过聚类法得到5个典型

总裁余(余登武)博客 7681

图解 你管这破玩意儿叫指针?

本系列分三篇,用破玩意的方式彻底理解好指针的本质: 你管这破玩意叫指针 -- 基础篇 你管这破玩意叫指针 -- 进阶篇 你管这破玩意叫指针 -- 变态篇

yyaannnnnnnn的博客 193

工业4.0必备:C#上位机+数字孪生 生产线实时监控与智能预警系统(工业级实战)

数据割裂:PLC、传感器、工业相机的数据散落在不同系统,想看全局生产状态要切换N个软件,“数据孤岛”导致决策滞后;故障难预判:设备突发故障时,只能停机排查,平均故障响应时间超30分钟,一条生产线停工1小时损失超10万;可视化差:传统监控只有冰冷的数字和2D图表,设备运行状态、生产流程、物料流转无法直观感知,新人上手需3个月才能熟悉产线。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 661

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

C语言:指针详解【图解 + 练习】

本篇博客要搞懂什么是取地址( & ),什么是解引用( * )、学习一级指针,二级指针、搞懂 数组指针和指针数组、发现指针和数组的关系,包括一维、二维数组名,&数组名;

2302_76941579的博客 4242

IDEA的使用指南

IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.

图解C++指针与引用的区别

文章目录一、理解指针的基础,重要指数5星二、指针2.1是什么2.2如何使用指针操作变量2.3为什么使用指针三、引用3.1引用是什么3.2引用的简单例子3.3使用引用注意点四、指针与引用的区别4.1为什么C++要引入指针4.2指针不足之处4.3引用改善指针 一、理解指针的基础,重要指数5星 一个变量的组成:变量地址,变量名,变量值 如int i=10 二、指针 2.1是什么 指针用于存放一个变量在...

shang_0122的博客 4226

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

指针图解——指针救命神器

就像高数的二重积分一样,指针也有它自己的定义,下面的这句话牢牢记住,期末要考(哈哈,开个玩笑)指针是一个变量,其值为另一个变量的内存地址指针是一个变量,其值为另一个变量的内存地址指针是一个变量,其值为另一个变量的内存地址重要的话说三遍这就是指针的定义请大家看一下下面的代码正确与否int *p;//输出p的地址显然是不对的,因为p并没有指向具体地址,它是一个野指针,就好比你拿扑克牌当酒店房卡使,人家还以为你来斗地主呢。所以声明指针后一定要说明它指向的地址int a=10;int *p;

2401_88685396的博客 900

C++多级指针图解

graph表示解引用graph,也就是访问graph指向的位置。是已经分配好的,所以这行代码的意思是将的值(即指针)赋给graph指向的内存位置。将指向的对象的指针赋给graph指向的位置。在执行此操作后,*graph和会指向相同的实例。

solarsaber的专栏 438

70%新手卡关!C语言指针完全指南:内存图解+悬空指针避坑

在C语言的学习道路上,指针堪称是一座让众多新手望而生畏的大山。据统计,约70%的C语言初学者会在指针这一章节遭遇困境。指针之所以如此难以掌握,是因为它涉及到计算机内存的底层操作,需要对内存模型有深入的理解。本文将为你提供一份全面的C语言指针指南,通过详细的内存图解和对悬空指针等常见问题的分析,帮助你彻底攻克指针这一难关。

星辰夜语的博客 984

【图解】指针八大笔试题【附指针总结】

指针笔试题 文章目录❤引言❤????第1️⃣题????第2️⃣题????第3️⃣题????第4️⃣题????第5️⃣题????第6️⃣题????第7️⃣题????第8️⃣题 ❤引言❤ 待完善 ????第1️⃣题 //第一题 #include <stdio.h> int main() { int a[5] = { 1, 2, 3, 4, 5 }; int* ptr = (int*)(&a + 1); printf("%d,%d", *(a + 1), *(pt

哆啦A梦_PJYA的博客 771

C++指针案例及图解

本文指针的基础用法做了一些案例,望有所帮助✨✨✨

qq_54334713的博客 323

指针太难?这篇图解教程让你秒懂

在C和C++等编程语言中,指针是一个既强大又令人头疼的概念。很多初学者在接触指针时会感到困惑,觉得它难以理解和掌握。然而,指针在内存管理、数据结构实现、函数参数传递等方面有着重要的应用,是编程中不可或缺的一部分。本文将通过详细的图文说明和丰富的代码示例,帮助你轻松理解指针的概念和使用方法。

星辰夜语的博客 1122

C语言指针入门,图解+实例

1.指针是什么 指针是内存中一个最小的单元编号,也就是地址 通常我们口中说的指针其实是指针变量:变量中存放着地址 那么地址,内存,指针又有怎样的关系? 为了对内存更方便的管理使用,我们把内存划分为一个一个小格子 一个内存单元是1个字节 为了很好的定位到内存单元,我们给每个单元一个编号,这个编号也就是地址 指针变量就是存放我们需要的地址,方便我们需要时直接使用 如何去创建指针变量,并且存放地址呢? int a=0; int* p=&a;//此处*代表创建的是指针变

sun的博客 3875

图解指针数组与数组指针

学习了C语言,经常会记不得数组指针与指针数组的区别,下面给出图解,一目了然:

weixin_43955053的博客 264

(图解) 指针交换两个变量的值 swap C语言入门

欢迎关注笔者,你的支持是持续更博的最大动力 目录问题描述思路代码思考相关内容其他 问题描述 交换两个变量的值。 举例:m=3, n=4 交换后:m=4, n=3 思路 交换两个变量的值,也就是交换两块内存区域中储存的值。 而通过指针,能够对该指针指向对内存区域进行读写。 代码 //定义交换函数,形参为两个指向变量地址值的指针 void Swap(int * p1, int * p2){ //p1,p2是指针,类型:int *; *p1类型:int int tmp = *p1; //p1指向的.

橘子冰的博客 4626
上一篇: 人是怎么废掉的?
下一篇: 一不小心进入“决赛圈”,没“阳过”的怎么办?
码农翻身
码农翻身 《码农翻身》作者 《码农翻身》作者
博客等级 码龄8年 3万+粉丝 1084原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值