许多人听到这个名字就感到害怕,指针本身就没有完全搞懂,又有什么双重指针,现在这个东东非把我头搞昏不可。其实并没有那么可怕,但前面所讲的基础的确必须扎实。经小雅一分析,你会觉得指针并不难,真正难的是你没有找到好教程(玩笑)。
指针的好处就是,你只要对指针变量赋一个地址,你就可以通过这个地址去代替那个变量,从而操作那个变量上的数据。指针变量如果没有赋值,就不能操作数据,因此你必须要将某个变量的地址赋给指针变量,也就是让这个指针有了空间。动态分配空间也是先申请一块空间,然后将这块空间的地址赋给这个指针变量。
在C语言中不仅仅是变量的地址可以赋给指针,goto语句用的标签也可以赋给指针。标签其实就是一个地址,学过汇编语言的人就特别清楚这一点。下面这个例子是在Red Hatt Linux下用gcc编译实现的,遗憾的是Windows下并不支持。不过,如果我们能理解指针的功能也就达到目的了。
#include
<stdio.h>int
main(void
) {void
*ptr ;int
num; scanf("%d", &num);if
(num < 10) { ptr = &&succeed ; }else
{ ptr = &&failure ; }goto
*ptr ; succeed: printf("成功!") ;return
0; failure: printf("失败!") ;return
-1 ; }
函数指针并不是指函数的地址象指针一样可以被赋值,而是指将函数的固定地址赋给指针变量,从而用指针来代替函数名来操作。
一个函数定义好之后,它和变量一样,也有一个固定的地址,我们把这个地址赋给指针变量,这个指针就可以充当函数来使用。但要注意一点,函数的地址赋给指针变量的方法有点特殊,不能与普通变量一样赋值,否则编译系统就会误解成指针和函数结果的某种运算了。
#include
<stdio.h> //申明一个函数指针的类型。相当于函数申明。typedef int
(*pType) (int
) ;int
fact(int
number) {int
i , ret = 1 ;for
(i=1; i<=number; i++) { ret *= i ; }return
ret ; }int
main(void
) {int
num ; pType pt; //定义一个函数指针类型的变量 pt = fact; //将函数fact的地址赋给pt scanf("%d", &num); printf("%d的阶层=%d \n", num, fact(num)); //这是普通的函数调用 printf("%d的阶层=%d \n", num, (*pt)(num)); //这是函数指针的调用方法。注意:*pt一定要用括号括起来。return
0; }
上例中typedef语句在后面章节中细说,是用来自定义一个数据类型。当前的语句是typedef的特殊用法,pType是数据类型的名称,可以自己定,一般习惯用法全用大写。*pType两边的括号是必须的,是定义函数指针的标志。(*pType)前面的“int”数据类型是函数的返回值的数据类型,不是任意指定的,是你想要函数指针指向的函数的返回值的数据类型,当前例子中“fact”的返回值的数据类型。(*pType)后面和括号是参数,当前例子中“fact”后面的数据类型相一致。
上例中如果没有第04行的申明,第21行也可改为直接定义。“int
(*pt) (int
) ;”
函数指针经常被使用,但初学者或一般的开发者却很少使用。限于自身水平不高,小雅也只能很肤浅地、象征性地举例说明。
#include
<stdio.h> //申明一个函数指针的类型typedef void
(*pType) (int
,int
) ;void
max(int
m,int
n) { printf("最大值=[%d]\n", m>n ? m : n) ;return
; }void
min(int
m,int
n) { printf("最小值=[%d]\n", m<n ? m : n) ;return
; }void
fsq(int
m,int
n) { printf("平方和=[%d]\n", m * m + n * n) ;return
; } //定义一个用函数指针做参数的函数void
process(int
num1,int
num2, pType pt) { (*pt)(num1, num2); }int
main(void
) {int
x, y, i ; pType arr[] = {max, min, fsq}; //定义一个函数指针类型的数组 printf("请输入x和y的值:"); scanf("%d,%d", &x, &y) ; //用法一 process(x, y, max); //将函数max的地址作实参数 process(x, y, min); //将函数min的地址作实参数 process(x, y, fsq); //将函数fsq的地址作实参数 printf("\n"); //用法二for
(i=0; i<3; i++) { arr[i](x, y); //循环调用三个函数 }return
0; }