专题十一、指针和数组

指针和数组

  • 1. 指针的算术运算
    • 1.1 指针加上整数
    • 1.2 指针减去整数
    • 1.3 两个指针相减
    • 1.4 指针比较
    • 1.5 指向复合常量的指针
  • 2. 指针用于数组处理
  • 3. 用数组名作为指针
    • 3.1 数组型实际参数(改进版)
    • 3.2 用指针作为数组名
  • 4. 指针和多维数组
    • 4.1 处理多维数组的元素
    • 4.2 处理多维数组的行
    • 4.3 处理多维数组的列
    • 4.4 用多维数组名作为指针
  • 5. C99 中的指针和变长数组

本专题介绍 C 语言中指针指向数组元素时的算术运算、关系运算和判等运算,通过示范指针处理数组元素的方法,揭示指针和数组之间的联系。

参考资料:《C 语言程序设计 · 现代方法 第 2 2 2 版》

1. 指针的算术运算

在专题十中我们知道,指针可以指向数组元素。例如,假设已经声明 ap 如下:

int a[10], *p;

通过下列写法可以使 p 指向 a[0]

p = &a[0];

其结果可以用图形方式表示为:
指针与数组
现在可以通过 p 访问 a[0]。例如,可以通过下列写法把值 5 5 5 存入 a[0] 中:

*p = 5;

下面显示的是现在的情况:
指针数组赋值
通过在 p 上执行指针算术运算(或者地址算术运算)可以访问数组 a 的其他所有元素。C 语言支持 3 3 3 种(而且只有 3 3 3 种)格式的指针算术运算:

  • 指针加上整数
  • 指针减去整数
  • 两个指针相减

下面仔细研究一下每种运算。下面的所有例子都假设有如下声明:

int a[10], *p, *q, i;

1.1 指针加上整数

指针 p 加上整数 j 产生指向特定元素的指针,这个特定元素是 p 原先指向的元素后的 j 个位置。更确切地说,如果 p 指向数组元素 a[i],那么 p + j 指向 a[i + j](当然,前提是 a[i + j] 必须存在)。

下面的示例说明指针的加法运算,插图说明计算中 pq 在不同点的值。
指针加上整数

1.2 指针减去整数

如果 p 指向数组元素 a[i],那么 p - j 指向 a[i - j]。例如:
指针减去整数

1.3 两个指针相减

当两个指针相减时,结果为指针之间的距离(用数组元素的个数来度量)。因此,如果 p 指向 a[i]q 指向 a[j],那么 p - q 就等于 i - j。例如:
两个指针相减
在一个不指向任何数组元素的指针上执行算术运算会导致未定义的行为。此外,只有在两个指针指向同一个数组时,把它们相减才有意义。

1.4 指针比较

可以用关系运算符(<<=>>=)和判等运算符(==!=)进行指针比较。只有在两个指针指向同一数组时,用关系运算符进行的指针比较才有意义。比较的结果依赖于数组中两个元素的相对位置。例如,在下面的赋值后 p <= q 的值是 0 0 0,而 p >= q 的值是 1 1 1

p = &a[5];
q = &a[1];

1.5 指向复合常量的指针

指针指向由复合字面量(见专题八)创建的数组中的某个元素是合法的。例如:

int *p = (int []){3, 0, 3, 4, 1};

p 指向一个五元数组的第一个元素,这个数组包括 5 5 5 个整数 3 3 3 0 0 0 3 3 3 4 4 4 1 1 1。使用复合字面量可以减少一些麻烦,我们不再需要先声明一个数组变量,然后用指针 p 指向数组的第一个元素。

2. 指针用于数组处理

指针的算术运算允许通过对指针变量进行重复自增来访问数组的元素。下面这个对数组 a 中元素求和的程序段说明了这种方法。在这个示例中,指针变量 p 初始指向 a[0],每次执行循环时对 p 进行自增;因此 p 先指向 a[1],然后指向 a[2],依此类推。在 p 指向数组 a 的最后一个元素后循环终止。

#define N 10
...
int a[N], sum, *p;
...
sum = 0;
for (p = &a[0]; p < &a[N]; p++)sum += *p;

下图说明了前 3 3 3 次循环迭代结束时(即 p 自增操作前)asump 的内容。
在这里插入图片描述
for 语句中的条件 p < &a[N] 值得特别说明一下。尽管元素 a[N] 不存在,但是对它使用取地址运算符是合法的。因为循环不会尝试检查 a[N] 的值,所以在上述方式下使用 a[N] 是非常安全的。执行循环体时 p 依次等于 &a[0], &a[1], ..., &a[N - 1],但是当 p 等于 &a[N] 时,循环终止。

当然,改用下标可以很容易地写出不使用指针的循环。支持采用指针算术运算的最常见论调是,这样做可以节省执行时间。但是,这依赖于具体的实现,对有些编译器来说,实际上依靠下标的循环会产生更好的代码。

* 运算符和 ++ 运算符的组合

C 程序员经常在处理数组元素的语句中组合 *(间接寻址)运算符和 ++ 运算符。例如,把值存入一个数组元素中,然后前进到下一个元素。利用数组下标可以写成 a[i++] = j;。如果 p 指向数组元素,那么相应的语句将会是 *p++ = j;。因为后缀 ++ 的优先级高于 *,所以编译器把上述语句看成是 *(p++) = j;p++ 的值是 p,因此 *(p++) 的值将是 *p,即 p 当前指向的对象。

当然,*p++ 不是唯一合法的 *++ 的组合。例如,可以编写 (*p)++,这个表达式返回 p 指向的对象的值,然后将对象进行自增(p 本身是不变化的)。

表达式含义
*p++*(p++)自增前表达式的值是 *p,以后再自增 p
(*p)++自增前表达式的值是 *p,以后再自增 *p
*++p*(++p)先自增 p,自增后表达式的值是 *p
++*p++(*p)先自增 *p,自增后表达式的值是 *p

这几种组合中,最频繁见到的就是 *p++,它在循环中是很方便的。对数组 a 的元素求和时,可以把

for (p = &a[0]; p < &a[N]; p++)sum += *p;

改写成

p = &a[0];
while (p < &a[N])sum += *p++;

* 运算符和 -- 运算符有类似的组合方法。在专题九中我们实现了一个栈,原始版本的栈依靠名为 top 的整型变量来记录 contents 数组中 “栈顶” 的位置。现在用一个指针变量来替换 top,这个指针变量初始指向 contents 数组的第 0 0 0 个元素。

int *top_ptr = &contents[0];

下面是新的 push 函数和 pop 函数:

void push(int i)
{if (is_full())stack_overflow();else*top_ptr++ = i;
}int pop(void)
{if (is_empty())stack_underflow();elsereturn *--top_ptr;
}

3. 用数组名作为指针

指针的算术运算是数组和指针之间相互关联的一种方法,但这不是两者之间唯一的联系。下面是另一种关键的关系:可以用数组的名字作为指向数组第一个元素的指针。这种关系简化了指针的算术运算,而且使数组和指针更加通用。

例如,假设用如下形式声明 a

int a[10];

a 作为指向数组第一个元素的指针,可以修改 a[0]

*a = 7;					/* stores 7 in a[0] */

可以通过指针 a + 1 来修改 a[1]

*(a + 1) = 12;			/* stores 12 in a[1] */

通常情况下,a + i 等同于 &a[i],两者都表示指向数组 a 中元素 i 的指针,并且 *(a + i) 等价于 a[i],两者都表示元素 i 本身。换句话说,可以把数组的取下标操作看成是指针算术运算的一种形式。

数组名可以用作指针这一事实使得编写遍历数组的循环更加容易。例如下面这个对数组元素求和的循环

for (p = &a[0]; p < &a[N]; p++)sum += *p;

可以用 a 替换 &a[0],同时用 a + N 替换 &a[N]

for (p = a; p < a + N; p++)sum += *p;

虽然可以把数组名用作指针,但是不能给数组名赋新的值。试图使数组名指向其他地方是错误的:

while (*a != 0)a++;			/*** WRONG ***/

这一限制不会对我们造成什么损失:我们可以把 a 复制给一个指针变量,然后修改该指针变量:

p = a;
while (*p != 0)p++;

程序 reverse3.c:数列反向(改进版)

/* Reverses a series of numbers (pointer version) */#include <stdio.h>#define N 10int main(void)
{int a[N], *p;printf("Enter %d numbers: ", N);for (p = a; p < a + N; p++)scanf("%d", p);printf("In reverse order:");for (p = a + N - 1; p >= a; p--)printf(" %d", *p);printf("\n");return 0;
}

注意,scanf 函数的第二个实际参数是 p,不是 &p。因为 p 指向数组的元素,所以它是满足 scanf 函数要求的参数;而 &p 则是指向指向数组元素的指针的指针。

3.1 数组型实际参数(改进版)

数组名在传递给函数时,总是被视为指针。思考下面的函数,这个函数会返回整型数组中最大的元素:

int find_largest(int a[], int n)
{int i, max;max = a[0];for (i = 1; i < n; i++)if (a[i] > max)max = a[i];return max;
}

假设调用 find_largest 函数如下:

largest = find_largest(b, N);

这个调用会把指向数组 b 第一个元素的指针赋值给 a,数组本身并没有被复制。把数组型形式参数看作是指针会产生许多重要的结果。

  • 在给函数传递普通变量时,变量的值会被复制,任何对相应的形式参数的改变都不会影响到变量。反之,因为没有对数组本身进行复制,所以作为实际参数的数组是可能被改变的。为了指明数组型形式参数不会被改变,可以在其声明中包含单词 const
  • 给函数传递数组所需的时间与数组的大小无关。因为没有对数组进行复制,所以传递大数组不会产生不利的结果。
  • 如果需要,可以把数组型形式参数声明为指针,声明 a 是指针就相当于声明它是数组,编译器把这两类声明看作是完全一样的。例如,可以按如下形式定义 find_largest 函数:
    int find_largest(int *a, int n)
    {...
    }
    
    对于形式参数而言,声明为数组跟声明为指针是一样的;但是对变量而言,声明为数组跟声明为指针是不同的。声明 int a[10]; 会导致编译器预留 10 10 10 个整数的空间,但声明 int *a; 只会导致编译器为一个指针变量分配空间。在后一种情况下,a 不是数组,试图把它当作数组来使用可能会导致极糟的后果。例如,赋值 *a = 0; 将在 a 指向的地方存储 0 0 0,由于我们不知道 a 指向哪里,所以对程序的影响是无法预料的。
  • 可以给形式参数为数组的函数传递数组的 “片断”,所谓片断是指连续的数组元素组成的序列。假设希望用 find_largest 函数来定位数组 b 中某一部分的最大元素,比如说元素 b[5], ..., b[14]。调用 find_largest 函数时,将传递 b[5] 的地址和数 10 10 10,表明希望 find_largest 函数从 b[5] 开始检查 10 10 10 个数组元素:
    largest = find_largest(&b[5], 10);
    

3.2 用指针作为数组名

C 语言也允许把指针看作数组名进行取下标操作:

#define N 100
...
int a[N], i, sum = 0, *p = a;
...
for (i = 0; i < N; i++)sum += p[i];

编译器把 p[i] 看作 *(p + i),这是指针算术运算非常正规的用法。

4. 指针和多维数组

4.1 处理多维数组的元素

从专题七可知,C 语言按行主序存储二维数组;换句话说,先是 0 0 0 行的元素,接着是 1 1 1 行的,依此类推。 r r r 行的数组可表示如下:
在这里插入图片描述
使用指针时可以利用这一布局特点。如果使指针 p 指向二维数组中的第一个元素(即 0 0 0 0 0 0 列的元素),就可以通过重复自增 p 的方法访问数组中的每一个元素。

作为示例,一起来看看把二维数组的所有元素初始化为 0 0 0 的问题。假设数组的声明如下:

int a[NUM_ROWS][NUM_COLS];

显而易见的方法是用嵌套的 for 循环:

int row, col;
...
for (row = 0; row < NUM_ROWS; row++)for (col = 0; col < NUM_COLS; col++)a[row][col] = 0;

如果把 a 看成是一维的整型数组,那么就可以把上述两个循环改成一个循环了:

int *p;
...
for (p = &a[0][0]; p <= &a[NUM_ROWS - 1][NUM_COLS - 1]; p++)*p = 0;

循环开始时 p 指向 a[0][0]。对 p 连续自增可以使指针 p 指向 a[0][1]a[0][2]a[0][3] 等。当 p 达到 a[0][NUM_COLS - 1](即第 0 0 0 行的最后一个元素)时,再次对 p 自增将使它指向 a[1][0],也就是第 1 1 1 行的第一个元素。这一过程持续进行,直到 p 越过 a[NUM_ROWS - 1][NUM_COLS - 1](数组中的最后一个元素)为止。

虽然把二维数组当成一维数组来处理看上去像在搞欺骗,但是对大多数 C 语言编译器而言这样做都是合法的。但这样做是否是个好主意则要另当别论。这类方法明显破坏了程序的可读性,但是至少对一些老的编译器来说这种方法在效率方面进行了补偿。不过,对许多现代的编译器来说,这样所获得的速度优势往往极少甚至完全没有。

4.2 处理多维数组的行

为了访问到第 i 行的元素,需要初始化指针变量 p 使其指向数组 a 中第 i 行的元素 0 0 0p = &a[i][0];。对于任意的二维数组 a 来说,由于表达式 a[i] 是指向第 i 行中第一个元素(元素 0 0 0)的指针,前面的语句可以简写为 p = a[i];

为了了解原理,我们先回顾一下把数组取下标和指针算术运算关联起来的那个神奇公式:对于任意数组 a 来说,表达式 a[i] 等价于 *(a + i)。因此 &a[i][0] 等同于 &(*(a[i] + 0)),而后者等价于 &*a[i],又因为 &* 运算符可以抵消,也就等同于 a[i]

下面的循环对数组 a 的第 i 行清零,其中用到了这一简化:

int a[NUM_ROWS][NUM_COLS], *p, i;
...
for (p = a[i]; p < a[i] + NUM_COLS; p++)*p = 0;

因为 a[i] 是指向数组 a 的第 i 行的指针,所以可以把 a[i] 传递给需要用一维数组作为实际参数的函数。换句话说,使用一维数组的函数也可以使用二维数组中的一行。因此,诸如 find_largeststore_zeros 这类函数比我们预期的更加通用。最初设计用来找到一维数组中最大元素的 find_largest 函数现在同样可以用它来确定二维数组 a 中第 i 行的最大元素:

largest = find_largest(a[i], NUM_COLS);

4.3 处理多维数组的列

处理二维数组的一列中的元素就没那么容易了,因为数组是按行而不是按列存储的。下面的循环对数组 a 的第 i 列清零:

int a[NUM_ROWS][NUM_COLS], (*p)[NUM_COLS], i;
...
for (p = &a[0]; p < &a[NUM_ROWS]; p++)(*p)[i] = 0;

这里把 p 声明为指向长度为 NUM_COLS 的整型数组的指针。在 (*p)[NUM_COLS] 中,*p 是需要使用括号的;如果没有括号,编译器将认为 p 是指针数组(存放指针的数组),而不是数组指针(指向数组的指针)。表达式 p++p 移到下一行的开始位置。在表达式 (*p)[i] 中,*p 代表 a 的一整行,因此 (*p)[i] 选中了该行第 i 列的那个元素,(*p)[i] 中的括号是必要的,因为编译器会将 *p[i] 解释为 *(p[i])

4.4 用多维数组名作为指针

就像一维数组的名字可以用作指针一样,无论数组的维数是多少都可以采用任意数组的名字作为指针。思考数组 int a[NUM_ROWS][NUM_COLS];a 不是指向 a[0][0] 的指针,而是指向 a[0] 的指针。从 C 语言的观点来看,这样是有意义的。C 语言认为 a 不是二维数组而是一维数组,且这个一维数组的每个元素又是一维数组。用作指针时,a 的类型是 int (*)[NUM_COLS](指向长度为 NUM_COLS 的整型数组的指针)。

了解 a 指向的是 a[0][0] 有助于简化处理二维数组元素的循环。例如,为了把数组 a 的第 i 列清零,可以用

for (p = &a[0]; p < &a[NUM_ROWS]; p++)(*p)[i] = 0;

取代

for (p = a; p < a + NUM_ROWS; p++)(*p)[i] = 0;

另一种应用是巧妙地让函数把多维数组看成是一维数组。例如,思考如何使用 find_largest 函数找到二维数组 a 中的最大元素。我们把 a(数组的地址)作为 find_largest 函数的第一个实际参数,NUM_ROWS * NUM_COLS(数组 a 中的元素总数量)作为第二个实际参数:

largest = find_largest(a, NUM_ROWS * NUM_COLS);		/*** WRONG ***/

这条语句不能通过编译,因为 a 的类型为 int (*)[NUM_COLS]find_largest 函数期望的实际参数类型是 int *。正确的调用是:

largest = find_largest(a[0], NUM_ROWS * NUM_COLS);

a[0] 指向第 0 0 0 行的元素 0 0 0,类型为 int *(编译器转换以后),所以这一次调用将正确地执行。

5. C99 中的指针和变长数组

指针可以指向变长数组中的元素,变长数组是 C99 的一个特性。普通的指针变量可以用于指向一维变长数组的元素:

void f(int n)
{int a[n], *p;p = a;...
}

如果变长数组是多维的,指针的类型取决于除第一维外每一维的长度。下面是二维的情况:

void f(int m, int n)
{int a[m][n], (*p)[n];p = a;...
}

因为 p 的类型依赖于 n,而 n 不是常量,所以说 p 具有可改变类型。需要注意的是,编译器并非总能确定 p = a 这样的赋值语句的合法性。例如,下面的代码可以通过编译,但只有当 m = n m = n m=n 时才是正确的:

int a[m][n], (*p)[m];
p = a;

如果 m ≠ n m \ne n m=n,后续对 p 的使用都将导致未定义的行为。

与变长数组一样,可改变类型也具有特定的限制,其中最重要的限制是,可改变类型的声明必须出现在函数体内部或者在函数原型中。

变长数组中的指针算术运算和一般数组中的指针算术运算一样。还是那个对二维数组 a 的一列进行清零操作的例子,这次将二维数组 a 声明为变长数组:int a[m][n];,指向数组 a 中某行的指针可以声明为:int (*p)[n];,把第 i 列清零的循环如下:

for (p = a; p < a + m; p++)(*p)[i] = 0;

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

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

相关文章

log4j2的使用

基础用法 1. pom文件导入依赖 junit用来做测试 <dependency><groupId>org.apache.logging.log4j</groupId><artifactId>log4j-core</artifactId><version>2.5</version></dependency><dependency><groupId>org.…

国际网络专线多少钱一年

国际网络专线作为企业扩展业务的重要通信渠道&#xff0c;已经成为许多企业不可或缺的选择。然而&#xff0c;对 于许多企业来说&#xff0c;选择一条稳定、高质量的国际网络专线&#xff0c;并不是一件容易的事情。那么&#xff0c;国际 网络专线到底多少钱一年呢&#xff1f;…

BGP 邻居建立

拓扑图 配置 BGP进程号及为AS号 使用环回口建立BGP邻居关系时&#xff0c;需要指定更新源地址 EBGP在使用环回口建立邻居关系时&#xff0c;需配置EBGP多跳&#xff0c;环回口路由可达 EBGP的路由器存在IBGP邻居时&#xff0c;需要配置next-hop-local&#xff0c;保证下一跳…

适合tiktok运营的云手机需要满足什么条件?

TikTok作为一款全球热门的社交媒体平台&#xff0c;具有无限的市场潜力。然而&#xff0c;卖家在运营过程中常常会面临到视频0播、账号被降权、限流等问题&#xff0c;甚至可能因为多人同时使用一个IP而导致封号的风险。为了规避这些问题&#xff0c;越来越多的卖家将目光投向了…

C语言—指针(2)

回原点(......?)当我没讲&#xff0c;好难 1. 编写函数,要求用指针做形参&#xff0c;实现将二维数组(行列相同)的进行转置&#xff08;行列数据互换&#xff09;&#xff1a; ...不会写 /*1. 编写函数,要求用指针做形参&#xff0c;实现将二维数组(行列相同)的进行转置&a…

看小姐姐的效果棒极了,写了一个工具,逐帧解析视频转成图片,有没有带上商业思维的小伙伴一起研究下

一个突然的想法&#xff0c;促成了这个项目雏形。 原理是&#xff1a; 上传一个视频&#xff0c;自动将视频每一帧保存成图片 然后前端访问 就能实现如图效果 后端是python/flask 数据库mysql 前端uniapp 项目演示&#xff1a; xt.iiar.cn 后端代码如下&#xff1a; #学习…

【C深剖】数组名的细节

本系列博客为个人刷题思路分享&#xff0c;有需要借鉴即可。 引言&#xff1a;我想我说的这个数组名细节可能很多人并没有留意&#xff0c;现在先来C设计者这样设计也很合理。 就是数组名本质上是一个指针&#xff0c;但是这个指针的内容也就是说指向的空间是固定的&#xff0c…

unplugin-vue-components解决命名冲突

我们在vue项目中通常会利用unplugin-vue-components插件进行自定义组件的自动引入 注&#xff1a;如果不知道怎么配置unplugin-vue-components插件&#xff0c;欢迎看我整理的这篇&#xff1a; vue3项目配置按需自动引入自定义组件unplugin-vue-components 当出现同名文件时&a…

先进电机技术——感应电机与同步电机

一、感应电机 感应电机&#xff08;Induction Motor&#xff09;是一种广泛应用的交流电动机&#xff0c;其工作原理基于电磁感应定律。在感应电机中&#xff0c;定子绕组连接到电源后会因通入的交流电而产生一个旋转磁场。这个磁场在空间中是连续变化并以恒定的速度&#xff…

【医学大模型】Text2MDT :从医学指南中,构建医学决策树

Text2MDT &#xff1a;从医学指南中&#xff0c;构建医学决策树 提出背景Text2MDT 逻辑Text2MDT 实现框架管道化框架端到端框架 效果 提出背景 论文&#xff1a;https://arxiv.org/pdf/2401.02034.pdf 代码&#xff1a;https://github.com/michael-wzhu/text2dt 假设我们有一…

算法-矩阵置零

1、题目来源 73. 矩阵置零 - 力扣&#xff08;LeetCode&#xff09; 2、题目描述 给定一个 m x n 的矩阵&#xff0c;如果一个元素为 0 &#xff0c;则将其所在行和列的所有元素都设为 0 。请使用 原地 算法。 示例 1&#xff1a; 输入&#xff1a;matrix [[1,1,1],[1,0,1…

机器学习---规则学习(一阶规则学习、归纳逻辑程序设计)

1. 一阶规则学习 “一阶”的目的&#xff1a;描述一类物体的性质、相互关系&#xff0c;比如利用一阶关系来挑“ 更好的”瓜&#xff0c;但实际应用 中很难量化颜色、 …、敲声的属性值。一般情况下可以省略全称量词。 命题逻辑&#xff1a;属性-值数据 色泽程度&#xff1a…

CSS:BFC

BFC&#xff0c;Block Formatting Context&#xff0c;块级格式化上下文&#xff0c;是一个独立的渲染区域或隔离的独立容器&#xff0c;它决定了其子元素如何布局&#xff0c;并且与这个区域外部的元素无关。 形成 BFC 的条件 float 的值不为 none&#xff08;left、right&a…

爬虫入门一

文章目录 一、什么是爬虫&#xff1f;二、爬虫基本流程三、requests模块介绍四、requests模块发送Get请求五、Get请求携带参数六、携带请求头七、发送post请求八、携带cookie方式一&#xff1a;放在请求头中方式二&#xff1a;放在cookie参数中 九、post请求携带参数十、模拟登…

HTTPS网络通信协议基础

目录 前言&#xff1a; 1.HTTPS协议理论 1.1协议概念 1.2加密 2.两类加密 2.1对称加密 2.2非对称加密 3.引入“证书” 3.1证书概念 3.2数据证书内容 3.3数据签名 4.总结 前言&#xff1a; 了解完HTTP协议后&#xff0c;HTTPS协议是HTTP协议的升级加强版&#xff0c…

设计模式二:代理模式

1、什么是动态代理 可能很多小伙伴首次接触动态代理这个名词的时候&#xff0c;或者是在面试过程中被问到动态代理的时候&#xff0c;不能很好的描述出来&#xff0c;动态代理到底是个什么高大上的技术。不方&#xff0c;其实动态代理的使用非常广泛&#xff0c;例如我们平常使…

unity 使用VS Code 开发,VS Code配置注意事项

vscode 对应的插件&#xff08;unity开发&#xff09; 插件&#xff1a;.Net Install Tool,c#,c# Dev Kit,IntelliCode For C# Dev Kit,Unity,Unity Code Snippets 本人现在是用了这些插件 unity需要安装Visual Studio Editor 1、.Net Install Tool 设置 需要在设置里面配置…

jvm gc日志拿取与分析思路

前言 参考文章:Java中9种常见的CMS GC问题分析与解决 - 美团技术团队 排查过程 进入容器里 生产应用是跑在docker上的&#xff0c;所以需要先进入到应用里面去&#xff0c;步骤如下 1. docker ps 找到对应的应用id&#xff0c;比如 zxc 2. 进入容器内部 docker exec -it 7690…

Elasticsearch:什么是搜索引擎?

搜索引擎定义 搜索引擎是一种软件程序或系统&#xff0c;旨在帮助用户查找存储在互联网或特定数据库中的信息。 搜索引擎的工作原理是对各种来源的内容进行索引和编目&#xff0c;然后根据用户的搜索查询向用户提供相关结果列表。 搜索引擎对于希望快速有效地查找特定信息的用…

怎么清理mac系统缓存系统垃圾文件 ?怎么清理mac系统DNS缓存

很多使用苹果电脑的用户都喜欢在同时运行多个软件&#xff0c;不过这样会导致在运行一些大型软件的时候出现不必要的卡顿现象&#xff0c;这时候我们就可以去清理下内存&#xff0c;不过很多人可能并不知道正确的清内存方式&#xff0c;下面就和小编一起来看看吧。 mac系统是一…