进阶C语言 第二章-------《进阶指针》 (指针数组、数组指针、函数指针、回调指针)知识点+基本练习题+深入细节+通俗易懂+完整思维导图+建议收藏

news2024/11/15 4:40:56

绪论

        书接上回,通过对数据类型进阶的认识,你肯定对各种数据类型在内存中如何存储有了了解。虽然说,这方面可能对你的编程能力没什么进步。但是,他是一本内功秘籍,当我们遇到了这方面的问题时我们可以知道可能是哪一方面出了问题。本章进阶指针,可能会有更多的知识点和更复杂的问题,但其实只要你对初阶的知识有很好的认识他也是小ks。

最后祝大家新年快乐,万事如意!

所以安全带系好,发车啦(建议电脑观看)。

        附:红色,部分为重点部分;蓝颜色为需要记忆的部分(不是死记硬背哈,多敲);黑色加粗或者其余颜色为次重点;黑色为描述需要

思维导图:


 

要XMind思维导图的话可以私信哈

目录​​​​​​​

1.字符指针

2.指针数组

2.1指针数组的定义和使用方法

3.数组指针

3.1  定义

3.2  &数组名与数组名

3.3数组指针的使用​​​​​​​

4.数组传参、指针传参

4.1 一维数组和指针数组传参

4.2 二维数组传参

4.3一级指针传参

4.4二级指针传参

5.函数指针

5.1.1函数指针的创建

5.1.2函数指针的使用

6.函数指针数组

6.1函数指针数组定义

7.指向函数指针数组的指针

8.回调指针

8.1.1回调函数的定义:


1.字符指针

1.1

知识点:

字符指针常见的的使用情况:

int main()
{
    char a = 'a';
    //字符指针
    //1.
    char * pa = &a;
    //2.
    char * pa = "abcd";
    return 0;
}

在第一种情况时:是直接将a的地址存进了一个指针中这个指针叫字符指针

在第二种情况时:是将字符串"abcd"中的首元素的'a'字符的地址存进一个字符指针中 (在常量字符串中他产生的值就是'a'字符的地址即"abcd" == &'a' )

细节(注意点):

常量字符串不能被修改、两相同的常量字符串完全相同

即当char * pa= "abcdef"时

*pa = 'w'(这样时错误的)

再如:

char arr[] = "abcdef";

arr = "cdefg";

这样同样是不行的

练习:

#include<stdio.h>
int main()
{
    char arr1[] = "abcdef";
    char arr2[] = "abcdef";

    const char *arr3 = "abcdef";
    const char *arr4 = "abcdef";

    if(arr1 == arr2)
        printf("same\n");
    else
        printf("no same\n");

    if(arr3 == arr4)
        printf("same\n");
    else
        printf("no same\n");

    return 0;
}

分析: 

首先,有2个数组变量arr1 arr2存放着字符串,并且还有两个字符指针存放着常量字符串的首元素地址

其次,因为两个数组会创建两个不同的空间即就会导致其数组名表示的首元素地址不同;而对于arr3 和 arr4 来说虽然他们将‘a’字符的地址存放在不同的空间,但是其指针变量的变量名就表示其内存中所存的地址(3、4都常量字符串的首元素地址)

最后,通过上面标红的字就可以推出最终将打印 no same   、 same        

附这里我们需要注意的是arr1 arr2  arr3 arr4 他们分别代表着意思

数组名:首元素的地址 

指针变量的变量名:代表着存放的地址

2.指针数组

2.1指针数组的定义和使用方法

知识点:

指针数组,字如其名是一个存放了多个指针的数组

我们不妨那整形数组、字符数组对应了来看

而我们有知道指针(变量)使用用来存放地址的,所以我们在为int * arr[4] 初始化时应该存放地址进去 

细节(具体):

对于指针数组的使用:

#include<stdio.h>
int main()
{
	char* arr[4] = { "abcd","hehe","blog","nb" };//常量字符串产生的是其首元素的地址
	for (int i = 0; i < 4; i++)
	{
		printf("%s ", arr[i]);
	}

	return 0;
}

练习:

 通过指针数组来模拟实现二维数组:

为什么可以直接写成arr[][]的形式,是因为你看arr[ i ][ j ]第一个  arr[i] 就是找到了 存放在指针数组中各个数组的地址(即数组名) 当i为0时(arr[ 0 ]  == arr1 ):arr1 [ j ]  是不是就是变成了数组的表示方法

当然我们也可以吧arr [ i ] [ j ]表示成 *(arr[ i ] + j )


3.数组指针

3.1  定义

知识点:

同整形指针、字符指针一样他是一种存放数组的指针

整形指针:int * p;

字符指针:char * p;

不难发现他们是由 所指向地址的类型     +     * (表示变量是一个指针)  +   变量名  组成的(这点很重要会贯穿后面指针的内容次处称为指针的3步原则

所以同理,数组指针他也是如此组成的:

int arr[ 4 ] = {1,2,3,4};

int (*parr)[ 4 ] = &arr;

此时的地址数组的类型为int  [ 4 ] *代表其为一个指针加上括号是因为防止因为[ ] 的优先级比 * 的优先级高而导致变成 指针数组   、 再加上变量名 就成了数组指针

3.2  &数组名与数组名

知识点:

数组名在讲数组内容处已经提过为:这个数组的首元素的地址

&数组名:如int arr[ 10 ] = {0}; arr表示数组名,那么取地址的数组名就真正的表示这个数组

细节:

下面通过代码来更加详细的解释:

int main()
{
	int arr[10] = { 0 };

	printf("%p\n", &arr[0]);//首元素的地址

	printf("%p\n", arr);//数组名

	printf("%p\n", &arr);//整个数组的地址


	return 0;
}

此处可以发现他们三个的地址都相同,但是有什么不同地方呢?让我们继续往下

	int main()
	{
		int arr[10] = { 0 };

		printf("%p\n", &arr[0]);//首元素的地址
		printf("%p\n", &arr[0]+1);//首元素的地址

		printf("%p\n", arr);//数组名
		printf("%p\n", arr+1);//数组名


		printf("%p\n", &arr);//整个数组的地址
		printf("%p\n", &arr+1);//整个数组的地址



		return 0;
	}

此处当我们+1后,可以发现数组名的结果和&arr[0]的效果(加了4byte)是一样的都是,而&arr却加了40(70-48 == 28,十六进制不够接16,转化成十进制就是40byte)

所以,最终得出结论就是

  1. arr(除了两种特别情况外)都表示首元素的地址
  2. &arr 则直接表示整个数组
  3. 他们的不同处在于,代表的意义不一样

最终与上面所讲到的数组指针结合:

int arr[ 4 ] = {1,2,3,4};

int (*parr)[ 4 ] = &arr;

此处的数组指针和指针数组就有着明显的区别:

一个是存整个数组的地址的,一个是存数组中的各个数的地址的。

int * arr[4] = {arr,arr+1,arr+2,arr+3};

int (*p)[4] = &arr;

3.3数组指针的使用

直接通过代码注释的形式来展示;

//对于一维数组时
int main()
{
	int arr[10] = { 1,2,3,4,5,6,7,8,9,10 };
	int(*p)[10] = &arr;
	for (int i = 0; i < 10; i++)
	{
		printf("%d ", (*p)[i]);//通过(*p)找到整个数组 * &arr等于arr再通过下标引用找到对应
	}
        //而对于一维数组来说这样写反而有点冗余了,不如直接用指针*(p+i)
	return 0;
}

//对于二维数组来说
void test(int(*p)[4], int r, int c)//将二维数组的首元素传进其表示二维数组的第一行即一整个数组
{
	int i = 0;
	for (i = 0 ;i < r; i++)//i表示访问的行
	{
		int j = 0;
		for (j = 0; j < c; j++)
		{
			printf("%d", (*(p + i))[j]);//访问第i行j列
          //printf("%d", p[i][j]);p[i] == *(p+i)
		}
		printf("\n");
	}

}
int main()
{
	int arr[3][4] = { {1,2,3,4},{2,3,4,5},{3,4,5,6} };
	test(arr, 3, 4);
}

附:当在函数内接收一个二维数组时,方块内放到是二维数组的列宽

注意点:

  1. 数组指针*p = * &arr = arr
  2. int (* parr[10])[5]:

4.数组传参、指针传参

4.1 一维数组和指针数组传参

能够接收一维数组和指针数组的参数有:

对数据的参数进行接收一般有两种情况:

  1. 直接和原类型数据相同
  2. 传过来地址用指针接收;此时注意满足 类型 + * + 变量名 这一指针确定规则即可,如接收指针数组时用到的是二级指针,而不是一级指针的原因是原本传过来的类型就是int * 的类型所以要  类型 + *   所以就应该写成二级的int *  * ,或者还可以理解为传过来的是指针的地址,所以要用二级指针接收。
void test1(int arr[])//括号内加不加数组大小都行
{
	;
}

void test1(int* parr)
{
	;
}


void test2(int* arr2[])
{
	;
}

void test2(int** arr2)
{

	;
}

int main()
{
	int arr1[10] = { 0 };
	int* arr2[10] = { 0 };
	test1(arr1);
	test2(arr2);
	return 0;
}

4.2 二维数组传参

知识点:

同上这总结一般只有两种情况:

同上,也就是用原类型/指针类型

分析:

int main()
{
	int arr[3][4] = {0};
	test(arr);
	return 0;
}

test(arr)中的arr是数组名,数组名表示首元素的地址,而此处是一个二级数组,所以数组名就表示成了第一行arr[0]的地址即&arr[0],他是一个数组(第一行),所以我们在用指针时就应该用数组指针来存数组

所以,最终能在test函数中接收的参数类型有:

int arr[][COL]//此处行可以省略但是列不能省略

int (*parr)[COL]//数组指针接收数组

可能会感觉二级指针可以接收,但是事实上是不行的因为

二级指针:接收的应该是一级指针的地址(而不是数组的地址,

报错如下:

4.3一级指针传参

知识点:

一级指针传参时:直接用相同类型接收即可(不能用指针接收了此处因为二级指针是接收一级指针的地址的,并且其余的也用不了)

void test(int* p)
{
	;//code
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7 };
	int* p = arr;
	test(p);
	return 0;
}

反过来思考:

函数以一级指针接收时传的参数可以是什么?

不难可以想出,首先什么是以指针接收的无非就是地址,而在函数内还要加一个可能就是传过来的值的原本的类型也是指针。

所以最终的可能性就是:

传递一个变量的地址test(&a)、一维数组名(首元素的地址)test(arr)

以及指针变量名test(p)  (和上面的代码一样)


4.4二级指针传参

知识点:

同一级指针:你传的是一级指针的就用一级指针接收、传的是二级指针就用二级指针接收

void test(int** ptr)
{
	;//code
}

int main()
{
	int arr[] = { 1,2,3,4,5,6,7 };
	int* p = arr;
	int** pa = &p;
	test(pa);//pa 其实可以看成存着 &p
	test(&p);//传的是一级指针的地址其原理和二级指针变量名一样都是&p
	return 0;
}

反过来:当函数参数是一个二级指针接收

二级指针接收一级指针的地址:

所以可以是:

int * p = NULL;
int **parr = &p;

test(&p);

test(parr);

还可以存指针数组:因为指针数组内存的都是一个个一级指针

如:int * arr[10] 这里面存了10个int类型的指针

所以当我们把arr数组名传进去的时候就表示吧首元素的地址(&arr[0] == & (int *))及第一个一级指针的地址传了进去所以是一级指针就可以用二级指针来接收

5.函数指针

5.1

知识点:

函数指针:一个存储函数地址的指针

其表现形式为:类型  + * +变量名 = 函数的地址

细节:

5.1.1函数指针的创建

下面通过代码来具体的展示:

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 3;
	int b = 2;
	Add(a, b);
	//函数指针 类型+ * + 变量名 = 函数的地址
	//此处Add的类型为 int (int , int)
	int (*ptr)(int, int) = &Add;
	int (*ptr)(int, int) = Add;//此处函数名和数组名类似都可以表示其地址

	return 0;
}

5.1.2函数指针的使用

同指针一样,我们存了函数的地址所以就可以解应用找到这个函数   (*ptr)(a,b)  ==  Add(a,b)

在平常我们使用函数时是直接Add(a,b) 的 ,所以我们在使用(*ptr)(a,b)时甚至也可以直接写成ptr(a,b)

代码即:

int Add(int x, int y)
{
	return x + y;
}

int main()
{
	int a = 3;
	int b = 2;
	Add(a, b);
	//函数指针 类型+ * + 变量名 = 函数的地址
	//此处Add的类型为 int (int , int)
	int (*ptr)(int, int) = &Add;
	//上下一样  即:&Add == Add
	int (*ptr)(int, int) = Add;//此处函数名和数组名类似都可以表示其地址

	
	
	int ret = Add(a, b);
	// 等于
	int ret1 = (*ptr)(a, b);
	// 等于
	int ret2 = ptr(a, b);
	//即 Add(a,b) == (*ptr)(a,b) == ptr(a,b)


	return 0;
}
  1.  Add(a,b) == (*ptr)(a,b) ==  ptr(a,b)  //此处的(*ptr)中的*其实就是个摆设你甚至可以写成(***** ptr)(a,b) ,所以在我们用函数指针时可以存好一个函数的地址后可以直接写成 ptr(a,b)来代替Add(a,b),如过要写成(*ptr)(a,b)这种形式的话其中 (*ptr) 的括号不能少因优先级问题
  2. &Add ==  Add

附:*arr 可以看成 *(arr+0) 及   arr[0]   所以    **arr -> *(arr[0])  -> (arr[0][0])    (还可以将arr、arr[0] 看成首元素地址  *arr == arr【0】、* (arr[0]) -> arr[0][0]  )

我们在上面所用到的函数指针 ptr  其用法其实并不像上面那种而是一般会用于当把一个函数的地址传进到另一个函数内部时要在另一个函数内使用时可以用来接收这个地址 

练习:

(* (  void  ( * )  ( ) ) 0 )  ( )  : 这段代码的意义是:对0处的地址进行函数访问,不用传参

分析:

首先我们要知道最里面的void( * ) ( )  这是一个函数指针用来存地址 ,所以此处将整形0 用括号 强制转换成函数指针类型  就如 ptr 一样再(*(....)0)() 来访问0所指向的函数,因为函数类型中的参数是空的,所以也不用再进行传参。 

void (* signal(int ,void (*)(int)))(int);这段代码的意义是:对该函数进行声明

分析:

首先我们要知道,函数声明的结构是:返回类型 + 函数名 + 传参的类型  

而此处的返回类型是void (*) ( int )  ;函数名:signal   ;

传参的类型 : (int , void (*)(int))

可能此处不好看但是当写成返回类型为int就会变成:int signal(int , void (*)(int))

只是因为我们需要把函数名写到*的旁边所以看起来比较的奇怪:

现在分颜色来更清晰的写:void ( *  signal (int , void (*)(int)))(int);(注意声明时别漏了分号)

附:

我们还可以将复杂的函数指针给进行typedef陈一个简单点的类型,但是要注意写成(对指针类型要把名字放在星号旁边 ):

typedef void (* v_int) (int) ;//注意应该将想要改成的新类型名写到*的旁边

//那么就可以将signal函数的声明写成:
v_int signal (int , v_int);

6.函数指针数

6.1函数指针数组定义

知识点:

函数指针数组还是和其他数组一样遵循3步原则:

首先,在第五节我们已经知道了函数指针的写法如:void (*p) (int)

所以,3步原则已经满足了两:变量名、*  ,此处为函数指针数组不同于函数指针要加上数组所以就可以写成void (*p[5])(int) (   此处我们可以这样理解为什么要把[ ]放到里面:通过类比的方法看int arr[ ] 、int * arr[ ] 这些数组类型都是将他们的方括号放在了其变量名的后面 并且其类型写在了前面所以(又因为变量名要写到*好旁边所以写在里面),函数指针数组其本质还是个数组,所以类型为void   ...(int)、在加上其* 、变量名、数组 [ ] 就可以容易的想出void (*p[5]) (int)   )

细节:

函数指针数组的用法:其就和其余数组一样,如int arr[] 存的是多组相同类型(int)的元素(即多组整形1,2,3)

所以函数指针数组就是存多组函数指针类型所对应的数(即多组函数Add,test的地址)

练习:

函数指针数组(在某些时候又称为:转移表

通过函数指针数组实现计算器:

其用法和就是数组用法+函数指针的用法:先数组调用后在调用各个函数

#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void menu()
{
	printf("********************************\n");
	printf("**********1.Add   2.Sub*********\n");
	printf("**********3.Mul   4.Div*********\n");
	printf("**********   0.exit    *********\n");
	printf("********************************\n");
}

int Add(int x, int y)
{
	return  x + y;
}

int Sub(int x, int y)
{
	return  x - y;
}

int Mul(int x, int y)
{
	return  x * y;
}

int Div(int x, int y)
{
	return  x / y;
}

int main()
{
	int input = 0;
	int a = 0;
	int b = 0;
	do
	{
		menu();
		printf("请输入:");
		scanf("%d", &input);
        //下面的函数指针数组有一种可以转移的特性所以就可以称其转移表
		int(*p[5])(int, int) = { NULL,Add,Sub,Mul,Div };
		if (input == 0)
		{
			printf("退出计算器\n");
			break;
		}
		else if (input <= 4 && input >= 1)
		{
			printf("输入两个值:");
			scanf("%d %d", &a, &b);

			printf("%d\n", p[input](a, b));
		}
		else
		{
			printf("输入错误请重新输入\n");
		}

	} while (input);

		return 0;
}

7.指向函数指针数组的指针

7.1

知识点:

指向函数指针数组的指针 如何定义 同样的满足三步法 

首先类型 : 函数指针数组:如int (  *   p  [5]   )(  int   ,    int);  --- 标蓝的表示其类型

其次:他是一个数组,所以大致和数组指针相同:int (  *  p  )[5]    --- ( *p )确保其和*优先结合

最后,变量名 ,设其为pf       :   int* *  pf  )[ 5 ]  )(  int   ,  int  )   = &p;

细节(注意点):

虽然这个名字一大串,但是我们任然要记得他还是一个指针(地址)其大小仍然时4/8byte的

并且他是一个指向数组的指针所以若+1就是跳过了整个数组,当然若要用也和数组指针类似:

(*pf)找到整个数组 在进行小标访问 (*pf)[1] 

在转移表中进行测试Add(  [1]   ) 

练习:

在创建一个.....指针

//函数指针数组
int (*pa [20]) (char ,short);

//对于的函数指针数组的指针
int (*   (* ppa )  [20])  (char , short); 

8.回调指针

8.1

知识点:

8.1.1回调函数的定义:

回调函数就是一个通过函数指针调用的函数。如果你把函数的指针(地址)作为参数传递给另一个函数,当这个指针被用来调用其所指向的函数时,我们就说这是回调函数。回调函数不是由该函数的实现方直接调用,而是在特定的事件或条件发生时由另外的一方调用的,用于对该事件或条件进行响应。

细节:上面的大体意思有:

  1. 一个函数的地址(指针)被传递给另一个函数,在另一个函数内被间接性的调用,就成该函数(传地址的函数)为回调函数
  2. 其实回调函数,也就是函数指针所调用的函数
  3. 回调函数不是由自身的名字调用的,而是由另外的一方调用

练习:

下面是再次修改过后的转移表:

通过三个部分来展示其回调函数的特性

     其在第二张中其实就是用了函数指针来调用

本章完。预知后事如何,暂听下回分说。

持续更新大量C语言细致内容,三连关注哈

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

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

相关文章

使用 Grafana 请求API接口

目的: 使用Grafana 配合JSON API 插件 请求API接口,完成可视化,实现一些简单的请求功能 假设我们想将如下的API接口返回的json数据可视化 这里借用一下 小熊同学的 金融数据接口 用请求如下接口举例 https://api.doctorxiong.club/v1/fund/detail?code000001&startDat…

色环电容读数方法要点总结

🏡《电子元器件学习目录》 目录 1,概述2,读数方法3,颜色对照表3.1,颜色与电容值数字对照关系表3.2,颜色与10的指数数字对照关系表3.3,颜色与误差对照关系表4,总结1,概述 本文简单介绍色环电容的读数方法。 2,读数方法 如下图所示色环电容共有四个色环。最粗的被命名…

36.Isaac教程--复合消息

复合消息 ISAAC教程合集地址: https://blog.csdn.net/kunhe0512/category_12163211.html 文章目录复合消息测量类型使用复合消息的示例手臂关节速度基本轨迹命令手臂关节和末端执行器命令CompositeMetric 和 CompositeAtlas组件使用 CompositeMetric 计算距离在 Python 脚本中创…

使用bookdown构建新年日记本

简介 一年多前在 B 站发布了一个视频&#xff0c;预览了一下基于 bookdown 构建的日记本。本打算之后更个文字版本教程。结果一直忘了&#xff0c;最近通过一位读者的了解&#xff0c;打算把这个坑补上。 本文内容将展示如何使用 bookdown 模板并修改成自己的日记本。此外&…

某阿里员工提问:年终绩效自己给自己打3.25,会有什么后果?网友回答:必死无疑,不要犯傻!...

年底评绩效&#xff0c;大多数人都会给自己打高绩效&#xff0c;但有些人却反其道而行之。最近&#xff0c;一位阿里员工提出了这样的问题&#xff1a;自评绩效时给自己打3.25&#xff0c;会有什么后果&#xff1f;希望领导能不按常理出牌&#xff0c;给自己3.75。有人问&#…

HashMap1.7中的线程安全问题

文章目录前言正文前言 下面聊聊JDK1.7HashMap的死循环问题&#xff0c;在这之前首先要知道JDK1.7的HashMap底层是数组 链表的形式的 正文 下面给出JDK1.7的扩容代码 //扩容代码 void resize(int newCapacity) {//旧的数组Entry[] oldTable table;//旧的数组长度int oldCap…

SpringBoot+Vue--引入Element-UI创建首页-笔记2

关于Vue项目目录结构介绍 https://tiantian.blog.csdn.net/article/details/128666429?spm1001.2014.3001.5502 先安装引入Element-UI Element - The worlds most popular Vue UI framework i是install的缩写 安装完成后,可以看到package.json里已经引入 在main.js里引入…

linux系统的结构

Linux系统一般有4个主要部分&#xff1a;内核、shell、文件系统和应用程序。内核、shell和文件系统一起形成了基本的操作系统结构&#xff0c;它们使得用户可以运行程序、管理文件并使用系统。内核内核是操作系统的核心&#xff0c;具有很多最基本功能&#xff0c;它负责管理系…

Java基础之《netty(31)—用netty实现RPC》

一、需求说明 1、dubbo底层使用了netty作为网络通讯框架&#xff0c;要求使用netty实现一个简单的RPC框架。 2、模仿dubbo&#xff0c;消费者和提供者约定接口和协议&#xff0c;消费者远程调用提供者的服务&#xff0c;提供者返回一个字符串&#xff0c;消费者打印提供者返回…

S32G274A spi发送数组值不变问题

官方例程的spi问题 spi发送函数 下面是S32G两个spi从机发送函数 /** * brief SPI/DSPI异步传输。 * 这个函数使用提供的总线参数初始化异步传输 , 通过外部设备。 * param[in] ExternalDevice -指向传输数据的外部设备的指针 * param[in] TxBuffer -发送缓冲区的指针。 * pa…

3.1动态规划--矩阵连乘问题

写在前面&#xff1a;矩阵连乘的要点 1、最优解数组的含义--A[1:n]的最少数乘次数 2、数组的填写方向--斜着填 3、递推方程含义 今天开始动态规划的学习&#xff0c;动态规划与分治法类似&#xff0c;基本思想就是将待求解的问题分成若干子问题&#xff0c;先求解子问题&am…

Java 23种设计模式(2.创建者模式-工厂设计模式)

代码分析 通过代码的不同实现方式&#xff0c;了解工厂模式 代码分析之后有具体的讲解 1.业务和逻辑分开实现 public class Operation {public static double GetResult(double numberA,double numberB,String operate){double result 0;switch (operate){case "":r…

SpringBoot+Vue项目月度员工绩效考核管理系统

文末获取源码 开发语言&#xff1a;Java 框架&#xff1a;springboot JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7/8.0 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclipse/idea Maven包&#xff1a;Maven3.3.9 浏…

Kubernetes:通过 kubectl 插件 kubectl-tree 查看API对象层级关系

写在前面 分享一个小工具 kubectl-tree&#xff0c;用于查看 k8s API 对象层级关系比如对于有状态应用来讲&#xff0c;可以看到Deployment --> ReplicaSet --> Pod 的构成关系博文内容涉及&#xff1a;tree 插件的安装以及使用。理解不足小伙伴帮忙指正 岂其食鱼&#x…

Java---微服务---Nacos安装

Nacos安装1.Windows安装1.1.下载安装包1.2.解压1.3.端口配置1.4.启动1.5.访问2.Linux安装2.1.安装JDK2.2.上传Nacos安装包2.3.解压2.4.端口配置2.5.启动2.6.访问3.Nacos的依赖1.Windows安装 开发阶段采用单机安装即可。 1.1.下载安装包 在Nacos的GitHub页面&#xff0c;提供…

Java/JavaScript有哪些图形图像处理的框架?

文章目录一个小问题引发的学习热潮其它几个图形库Eclipse GEF框架Java图像库JS 的图形框架图形处理库图像编辑物理引擎流程图/组织图/图编辑等全景图/AR/VR3D库Javascript游戏编程库尾声一个小问题引发的学习热潮 一直对Java图形图像编程念兹在兹&#xff0c;书架上有几本相关…

2、IDEA的卸载与安装

文章目录2、IDEA的卸载与安装2.1 卸载过程2.2 安装前的准备2.3 安装过程2.4注册过程方式一&#xff1a;免费试用30天方式二&#xff1a;官网购买方式三&#xff1a;教育使用2.5 闪退问题【尚硅谷】idea实战教程-讲师&#xff1a;宋红康 生活是属于每个人自己的感受&#xff0c;…

3.1 卷积神经网络的应用领域|卷积的作用|卷积特征值的计算方法|得到特征图表示|步长与卷积核大小对结果的影响|边缘填充方法

文章目录卷积神经网络的应用领域卷积的作用卷积特征值的计算方法得到特征图表示步长与卷积核大小对结果的影响边缘填充方法卷积神经网络的应用领域 检测任务分类与检索超分辨率重构医学任务无人驾驶NVIDIA Tegra X1&#xff08;显卡 GPU&#xff09; 卷积的作用 卷积神经网络…

产品设计-基础控件-信息输出控件

产品设计-基础控件-信息输出控件1.1 走马灯1.1.1 图片轮播样式1.1.2 文字轮播样式1.2 折叠面板1.3 时间轴与步骤条1.3.1 时间轴1.3.2 步骤条1.4标签和徽标1.4.1 标签和徽标1.4.2 徽标1.5 面包屑与查询器1.5.1 面包屑1.5.2 查询器1.6 列表页与详情页1.6.1 列表页1.6.2 详情页1.7…

【实操案例十】函数操作 实例代码及运行效果图!

任务一&#xff1a;Mini计算器 # 任务一&#xff1a;Mini计算器 def calc(a, b, op):if op :return add(a, b)elif op -:return sub(a, b)elif op *:return mul(a, b)elif op /:if b ! 0:return div(a, b)else:return 0不能为除数&#xff01;def add(a, b):return a bde…