引子
上一节,我们通过例子知道,何如定义一个函数指针,并且把这个指针指向函数,现在我们进一步看看该如何定义和使用指向函数的指针变量。
定义
定义指向函数的指针变量一般形式为:
类型名 (* 指针变量名)(函数参数表列)
1 | int (*p)(int,int); |
注意,指针变量名必须用括号包起来。类型名,是指函数返回值的类型。
高树靡阴,独木不林。
上一节,我们通过例子知道,何如定义一个函数指针,并且把这个指针指向函数,现在我们进一步看看该如何定义和使用指向函数的指针变量。
定义指向函数的指针变量一般形式为:
类型名 (* 指针变量名)(函数参数表列)
1 | int (*p)(int,int); |
注意,指针变量名必须用括号包起来。类型名,是指函数返回值的类型。
前面,我们学习了,将指针指向变量、指向数组、指向字符数组,今天我们要引入一个新的概念,指针指向函数。
如果程序中定义了一个函数,那么在编译时,编译系统会为函数代码分配一段存储空间,我们称这段存储空间的起始地址
,称为这个函数的指针
。
所以,我们在捋顺一下:
指针指向变量:变量的地址
指针指向数组:数组首元素的地址
指针指向多维数组:数组首行元素的地址
指针指向字符数组:字符数组的首元素地址
指针指向函数:函数存储空间的起始地址
函数指针,意味着这个指针指向该函数:
1 | int (*p)(int,int); |
上面我们引入了很多例子,发现字符指针和字符数组仿佛使用起来差不多,真的是这样嘛?其实并不是,我们来细数字符指针和字符数组之间的区别吧!
字符指针和字符数组的组成上,有很大的不同。
字符指针:存放的是地址,是字符串首元素的地址。
字符数组:存储的是数组中的所有元素。
字符指针:我们可以对指针赋值,赋值一个新的地址给指针。
字符数组:我们不能给一个数组名赋值,职能给某一个数组元素赋值。
1 | //对字符指针变量赋值; |
前面,我们知道数组和指向数组的指针都可以作为函数参数,那么字符指针能否作为函数参数呢?答案是肯定的。
在 C 语言中,如果我们需要传递字符串,其实传递的是该字符串首元素的地址
,这样我们顺着地址移动指针就可以找到这个字符串了。
因为我们传递的是地址,所以改变了该地址后面的元素内容后,主调函数也会同时改变
。
用函数调用的方式,实现字符串的复制。
1 | #include <stdio.h> |
我们经常使用字符串,printf 中 " " 双引号之间
的内容可以直接输出,如今我们学习了指针的概念,通过指针来引用字符串,可以更加灵活和方便。
我们知道,在 C 语言中,字符串是存放在数组中的,想要引用一个字符串,可以有一下两种方法:
1 | #include <stdio.h> |
我们可以在printf 中用 %s 输出
,也可以通过数组名和下标
方式引用该字符串。
我们现在搞清楚了数组的地址以及如何使用指针来调用数组和数组元素,现在我们用指向数组的指针作为函数的参数
,看看有什么新玩法!
一维数组和多维数组的数组名可以作为函数参数
。我们如果使用指针变量作为形参,那么接收到的是从实参发送过来的地址
。
传送地址有两种方法:
有一个班,3名学生,各学4门,计算总平均分,以及第n个学生的成绩。
3个学生,各学4们,这就是一个 3X4 的多维数组。
计算第 n 个学生的成绩,这就是知道行元素,求列元素的总和。
1 | #include <stdio.h> |
前面,我们介绍了多维数组地址的概念,现在我们就学习如何用指针指向多维数组的元素。
我们看一个例子:
有一个 3X4 的二维数组,要求用指向元素的指针变量输出二维数组各个元素的值。
1 | #include <stdio.h> |
上面,我们让指针变量 pointer_a 指向了 a[0]的地址,然后通过不断的+1来向后移动指针,输出我们需要的内容,这种顺序输出比较简单。
前面我们知道,指针可以指向一维数组中的元素,同样的,指针也可以指向多维数组。这个概念比较绕,要清楚不同层的地址,以及不同的*号所指向的值,以及灵活运用数组名即首元素地址这一概念。
之前我们引入过多为数组的概念,很像行列式,例如:
1 | int a[2][3]={{1,2,3},{4,5,6}} |
上面的 a 是数组名
a 数组包含2个行元素
:a[0] 和 a[1]。
上面的每一个行元素又都是一个一维数组
每一个行元素又包含3个列元素
:a[0][0] 、a[0][1] 和 a[0][2]
我们可以理解为,二维数组
是数组的数组
,上面这个二维数组是由 2 个一维数组组成的,a[0] 和 a[1] 就是这两个一维数组的数组名。
我们先来捋一遍数组名和指针。数组名
是该数组的首元素起始地址
,说白了,也是一个地址,但这个地址是不变的,是固定的是一个常量
,数组名后面附加角标,叫可以表示该数组中的某一个元素的值。指针
是指向某一变量或数组的地址,和数组名一样,都是地址,但指针的内容是可以改变的,指针前加*号
就可以表示这个地址所指向的数据的值。
所以,我们现在知道了,数组和指针都表示的是一个地址。
我们照旧从一个例子出发,来理解这个概念,我们输入5个数到一个数组中,并且将数组中的5个数从大到小存储在数组中,接着依次输出这5个数。
1 | #include <stdio.h> |
前面我们学习了,引用数组有两种方式:
下标法:a[i]
指针法:(a+1) / (p+1)
今天我们实际来通过这两种方式引用一下数组元素看看能有哪些不同。
有一个整形数组 a,有10个元素,要求输出数组中的全部元素。
现在我们会使用3中方法,下标法、数组名计算元素地址、指针变量指向数组元素。
1 | #include <stdio.h> |
我们通过遍历数组的下标,输出数组。