【C语言进阶6——指针的进阶(3)-总结数组和指针】


前言

本文接着上文,继续学习指针进阶的知识点:指向函数指针数组的指针。

这基本上是最后一个知识点了。学完就对前面所学的数组和指针进行复习,知识点要常温常新:

  • 指向函数指针数组的指针
  • 总结数组和指针

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

7.1 用语法来解析—前置定语

乍得一看这个标题,这就是数组和指针的相互套娃呀,都惊呆了。

我们知道中文分析长难句的时候有语法,英语长难句也用语法分析,将长难句抽丝剥茧,化为简单句。

中文是一种语言,英语也是语言,C也是语言,下面用语法从字面意思分析指向函数指针数组的指针:

  1. 指针是一个名词,前面一坨(指向…的)是前置定语,用来修饰指针的。因此可以干掉定语,整个就剩指针了。
  2. 指向函数指针数组的指针说大白话,就是一个指针

在这里插入图片描述

  1. 这个前置定语又可拆分成,函数指针 + 数组。函数指针是名词,又作前置定语,修饰数组。
    因此可以干掉定语部分,就剩指针了。

  2. 说白了函数指针数组就是一个数组
    在这里插入图片描述

  3. 最终结果简化成指向数组的指针

7.2 定义

指向函数指针数组的指针:

  • 首先它是一个指针
  • 这个指针指向一个数组
  • 这个数组是函数指针数组
  • 数组里的每一个元素都是函数指针
  • 函数指针就是函数的地址,指针指向一个函数
  • 也可理解为指针保存了函数的地址,对指针解引用就能调用这个函数了
void test(const char* str)
{
    
    
	printf("%s\n", str);
}
int main()
{
    
    
	//函数指针pfun
	void (*pfun)(const char*) = test;
	//函数指针的数组pfunArr
	void (*pfunArr[5])(const char* str);
	pfunArr[0] = test;
	//指向函数指针数组pfunArr的指针ppfunArr
	void (*(*ppfunArr)[5])(const char*) = &pfunArr;
	return 0;
}

画图分析更加一目了然:
在这里插入图片描述

7.3 指向函数指针数组的指针的应用

在了解了反复套娃的定义后,举一个例子来说明它的作用:
应用上一篇博文的例子:简易计算器【C语言进阶5——指针的进阶(2)】6、函数指针数组

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 (*pfarr[4])(int, int) = {
    
    Add,Sub,Mul,Div};

    这一次加油改进,应用了指向函数指针数组的指针,代码长度又可以减少了
	int (*(* p3)[4])(int, int) = &pfarr;//p3是一个指向函数指针数组的指针
	int i = 0;
	for (i = 0; i < 4; i++)
	{
    
    
		//*p3是解引用,拿到函数指针数组的数组名 *(p3)=*(p3+0)=p3[0]
		//(*p3)[i]相当于pfarr[i],拿到了,数组的第i个元素,就是第几个函数的地址
		int ret = p3[0][i](3, 4);//传参数就能直接调用函数
		//int ret = (*p3)[i](3, 4);//传参数就能直接调用函数
		printf("%d\n", ret);
	}
	return 0;
}

这种数组和指针相互套娃的定义,了解就行了,遇到了能看懂就可以了,用到的情况还是比较少的。上面的例子完全就是符合内容的例子。

8、总结数组和指针

数组和指针应用广泛,知识点密集,容易混淆和遗忘,需要经常复习,因此,再次运用类比的方法,画图总结数组和指针:

8.1 数组小结

  • 整型数组
  • 字符型数组
  • 指针数组
  • 二维数组
    在这里插入图片描述
    其中,二维数组在基础阶段学过:
  • 理解arr[2][3]是一个2行3列的数组,每个元素都是int型
  • 学完指针后,我们换一个角度取理解它,使得对二维数组的认识升华了一个层次
int main()
{
    
    
	int arr[2][3] = {
    
     {
    
    1,2,3},{
    
    4,5,6}};

	printf("%d\n", sizeof(arr));//arr单独使用,求取的是整个数组的大小,24个字节
	printf("%d\n", sizeof(arr+1));//arr不是单独使用,代表的是首元素的地址,arr+1 就是第二个元素的地址,即第二行数组的地址,地址就是4/8 个字节
	printf("%d\n", sizeof(arr[0]));//arr[0]是第一行数组的数组名,单独使用,求取的是第一行数组的大小,12个字节
	printf("%d\n", sizeof(arr[0] + 1));//arr[0]不是单独使用,arr[0] + 1就是第一行第二个元素的地址,地址就是4/8 个字节
	printf("%d\n", sizeof(arr[0][1]));//第一行第二个元素的大小,4个字节
	return 0;
}

从调试中可以看到:

  • 数组arr[2][3]的类型是:int[2][3]
  • 数组有两个元素 arr[0] 和 arr[1]
  • arr[0]的类型是int [3],代表的是第一行数组,表示有3个元素,每个元素的类型是:int
  • arr + 1,类型是:int[3]*,表示数组第二个元素 arr[1] 的地址,指向第二行数组
  • arr[0]+ 1,类型是:int*,表示的是第一行数组第二个元素的地址

在这里插入图片描述

8.2 指针小结

  • 整型指针
  • 浮点型指针
  • 字符型指针
  • 数组指针
  • 函数指针
    在这里插入图片描述

8.3 数组指针套娃小结

  • 存放数组指针的数组
  • 存放函数指针的数组
  • 指向函数指针数组的指针

在这里插入图片描述
在这里插入图片描述


总结

数组和指针应用广泛,知识点密集,比较复杂,并且容易遗忘,要反复复习,温故而知新,要打下坚固的基础,不能盲目的赶学习进度,要按照自己的学习进度来,不要与别人比较。

在基础阶段学习了数组和指针的相关知识,就是进阶阶段相关知识点的基础,并且升华了一下。

到此为止,指针相关的知识点学习就告一段落了,下一篇将更新数组和指针的应用举例,从代码上来复习所学知识。

推荐一个在线画图的网页,之前用自动的画图,但是文字都是成图片了,不能直接编辑。今天尝试了网页绘图,保存默认的格式导出后,下一次打开还能直接编辑文字,感觉用的比画图好一些。

Flowchart Maker & Online Diagram Software

猜你喜欢

转载自blog.csdn.net/taibudong1991/article/details/124160745