(一) 用函數指針變量調用函數數組
能夠用指針變量指向整形變量、字符串、數組、結構體、也能夠指向一個函數。一個函數在編譯時被分配一個入口地址。這個入口地址就稱爲函數指針。能夠用一個指針變量指向函數,而後經過該指針變量調用此函數。用簡單的數值比較爲例:函數
1 #include <stdio.h>
2 #include <stdlib.h>
3
4 int main()
5 {
6 int max(int,int);
7 int (*p)(int,int);
8 int a,b,c;
9 p = max;
10 scanf("%d,%d",&a,&b);
11 c = (*p)(a,b);
12 printf("a=%d,b=%d,max=%d\n",a,b,c);
13 return 0;
14 }
15
16 int max(int x,int y)
17 {
18 int z;
19 if(x>y) z = x;
20 else z = y;
21 return(z);
22 }spa
main函數中的" c = max(a,b); " 包括了一次函數的調用。每個函數都佔用一段內存單元。所以,能夠用一個指針變量指向一個函數,經過指針變量來訪問它指向的函數。指針
第7行:int (*p)( int,int ); 用來定義 p 是一個指向函數的指針變量,該函數有 兩個整形參數,函數值爲整形。注意 *p 兩側的括號不可省略,表示 p 先與 * 結合,是指針變量,而後再與後面的 ( ) 結合,表示此指針變量指向函數,這個函數值 (即函數的返回值) 是整形的。若是寫成 int *p ( int,int ) ,因爲( )的優先級高於 *,它就成了聲明一個函數P( 這個函數的返回值是指向整形變量的指針)。code
賦值語句 p = max ; 做用是將函數 max 的入口地址賦給指針變量p。和數組名錶明數組首元素地址相似,函數名錶明該函數的入口地址。這時 p 就是指向函數 max 的指針變量,此時 p 和 max都指向函數開頭,調用 *p 就是調用 max 函數。可是p做爲指向函數的指針變量,它只能指向函數入口處而不可能指向函數中間的某一處指令處,所以不能用 *(p + 1)來表示指向下一條指令。內存
注意:字符串
(1) 指向函數的指針變量的通常定義形式爲:io
數據類型 (*指針變量名)(函數參數列表)編譯
這裏數據類型就是函數返回值的類型變量
(2) int (* p) ( int,int ); 它只是定義一個指向函數的指針變量 p, 它不是固定指向哪個函數的,而只是表示定義這樣一個類型的變量,它是專門用來存放函數的入口地址的。在程序中把哪一函數(該函數的值應該是整形的,且有兩個整形參數)的地址賦給它,他就指向哪個函數。在一個函數中,一個函數指針變量能夠前後指向同類型的不一樣函數。
(3) p = max; 在給函數指針變量賦值時,只需給出函數名而沒必要給出函數參數,由於是將函數的入口地址賦給 p ,而不涉及 實參和形參的結合問題,不能寫成 p = max(a,b);
(4) c = (*p)(a,b) 在函數調用時,只需將( *p ) 代替函數名便可,後面實參依舊。
(5) 對於指向函數的指針變量,像 p++ ,p+n.....是無心義的。
(二) 用指向函數的指針做爲函數參數
函數指針變量一般的用途之一就是把指針做爲參數傳遞到其餘函數。
函數的參數能夠是變量、指向變量的指針變量、數組名、指向數組的指針變量,也能夠是指向函數的指針也能夠做爲參數,以實現函數地址的傳遞,這樣就可以在被調用的函數中使用實參函數。
void sub ( int ( *x1) (int), int (*x2) (int,int) )
{
int a,b,i,j;
a = (*x1)(i); /* 調用 f1 函數 */
b = (*x2)(i)(j); /* 調用 f2 函數 */
}
若是實參爲兩個 函數名 f1 和 f2. 在函數首部定義x一、x2爲函數指針變量,x1指向的函數有一個整形形參,x2指向的函數有兩個形參。i 和 j 是函數f1 和 f2所要的參數。函數sub的形參 x一、x2(指針變量)在函數 sub 未被調用時並不佔用內存單元,也不指向任何函數。在sub被調用時,把實參函數 f1 和 f2的入口地址傳給形式指針變量 x1 和 x2.
既然在 sub 函數中要調用 f1 和 f2 函數,爲何不直接調用f1 和 f2而要用函數指針變量呢? 確實,若是隻是用到f1 和 f2 函數,徹底能夠在sub函數中直接調用f1 和 f2,而沒必要設指針變量 x1 和 x2。 可是,若是在每次調用sub時,調用的函數不是固定的,下次是f3 和 f4,再是f5 和 f6...這時用指針變量就比較方便了。