一個函數總是占用一段連續的內存區域,函數名在表達式中有時也會被轉換為該函數所在內存區域的首地址,這和數組名非常類似。
我們可以把函數的這個首地址(或稱入口地址)賦予一個指針變量,使指針變量指向函數所在的內存區域,然后通過指針變量就可以找到並調用該函數。這種指針就是函數指針。
函數指針的定義形式為:
retrunType(*pointerName)(param list); //數據類型(*指針變量名)();
//注意與二維數組的指針的定義區別開(int (*p)[4] = a;)
returnType 為函數返回值類型,pointerNmae 為指針名稱,param list 為函數參數列表。參數列表中可以同時給出參數的類型和名稱,也可以只給出參數的類型,省略參數的名稱,這一點和函數原型非常類似。
注意()
的優先級高於*,第一個括號不能省略,如果寫作returnType *pointerName(param list);
就成了函數原型,它表明函數的返回值類型為returnType *
。
比如
int *fun(int a,int b); //返回值是int類型指針的函數
int (*p)(int a,int b); //一個指向函數的指針
【實例1】用指針實現對函數的調用
#include <stdio.h>
//返回兩個數中較大的一個
int max(int a, int b){
return a>b ? a : b;
}
int main(){
int x, y, maxval;
//定義函數指針
int (*pmax)(int, int) = max; //也可以寫作int (*pmax)(int a, int b)
printf("Input two numbers:");
scanf("%d %d", &x, &y);
maxval = (*pmax)(x, y);
printf("Max value: %d\n", maxval);
return 0;
}
運行結果:
Input two numbers:10 50↙
Max valu:50
第 14 行代碼中pmax 是一個函數指針,在前面加 * 就表示對它指向的函數進行調用。
【實例2】
#include <stdio.h>
double f1(double x)
{ return x*x; }
double f2(double x, double y)
{ return x*y; }
double fun(double a, double b)
{
double (*f)();
double r1, r2;
f = f1 ; //函數指針的賦值,使f指向函數f1
//f=&f1; //第二種賦值方法
r1 = f(a); //函數指針第一種調用方法,也可以寫成 r1=(*f)(a);
f = f2 ; //使f指向f2
r2 = (*f)(a, b); //函數指針第二種調用方法,也可以寫成 r2=f(a,b);
return r1 + r2;
}
void main()
{ double x1=5, x2=3, r;
r = fun(x1, x2);
printf("\nx1=%f, x2=%f, x1*x1+x1*x2=%f\n",x1, x2, r);
}
運行結果:
x1=5.000000, x2=3.000000, x1*x1+x1*x2=40.000000
double(*f)();代表一個指向函數的指針變量; f=f1; 表示把函數f1賦值給f,使f指向f1;
注意:
(1)在給函數指針變量賦值時,只需給出函數名而不必給出參數值,因此直接令 f=f1 即可;
(2)注意上面代碼的注釋部份,賦值和調用的方法都有兩種,兩種都是可以的。
對於函數指針的賦值:函數名是一個地址,可以將他賦值給一個指向函數的指針。前面加了&符號其意義是一樣的。比如定義一個數組arr[],arr表示這個數組的首地址,但&arr同樣表示他的首地址。
對於函數指針的調用:比如你定義一個字符串指針char *str, 輸出str 他並不是輸出了地址,而是輸出存在該地址的值。