1. 程式人生 > >(C/C++學習)16.函數指針

(C/C++學習)16.函數指針

代碼段 調用函數 i++ ret 指針 本質 fff class 問題

說明:函數指針,顧名思義就是指向函數的指針。C/C++中函數名的本質其實就是一段代碼段空間的首地址。

1.定義

如下的 pf 就是一個函數指針,指向所有返回類型為 int,並帶有兩個 const int 參數的函數。需要註意的是 *pf 兩邊的括號不能少,否則面定義就變成了聲明了一個函數 pf其返回類型為 int *, 帶有兩個 const int 參數。

  1 int (*pf)(const int, const int);

2.取別名

如果每次都像上面那樣來聲明一個函數,那樣就顯得太復雜了,我們可以通過取別名的方式來簡化聲明復雜程度,如下:

  1 typedef int (*cmpFun)(const
int, const int);

這樣,cmpFun 就成了一種數據類型,可以用它來聲明和定義形如上面 pf 那樣的函數指針,比如:

  1 cmpFun pf = someFunction;
  2 cmpFun pf = &someFunction;

下面是一個測試代碼:

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int b)
  4 {
  5     printf("%d\t%d\n",a,b);
  6 }
  7 
  8 typedef void (*PF)(int a, int b);
  9
PF pf = myCmp; 10 11 int main(void) 12 { 13 (*pf)(1,2); 14 pf(1,2); 15 //兩種訪問方式都沒問題 16 return 0; 17 }

3.函數名作為地址的用法

上面提到了,函數名的本質是一個地址,那如果我們拿到這個地址,是否可以直接調用相應的函數呢?答案是肯定的!如下代碼,先打印出函數名所代表的地址,然後將其強轉成 PF 函數指針類型,然後在對其進行函數的調用。

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int
b) 4 { 5 printf("%d\t%d\n",a,b); 6 } 7 8 typedef void (*PF)(int a, int b); 9 PF pf = myCmp; 10 11 int main(void) 12 { 13 pf(1,2); 14 printf("%p\t%p\n",myCmp,&myCmp); 15 ((PF)(0x00401610))(1,2); 16 return 0; 17 }

上面代碼的打印結果為:

  1 1       2
  2 00401610        00401610
  3 1       2

4.回調函數

當函數作為參數而發起的調用函數的過程,就叫作函數的回調。函數的回調企事業是利用了函數指針這一概念。下面是一個回調示例:

  1 #include <stdio.h>
  2 
  3 void myCmp(int a,int b)
  4 {
  5     printf("%d\t%d\n",a,b);
  6 }
  7 void prin(void (*p)(int a,int b))
  8 {
  9     p(1,2);
 10 }
 11 
 12 int main(void)
 13 {
 14     prin(myCmp);
 15     return 0;
 16 }

5.函數指針數組

如下定義一個返回值和參數皆為 void 的函數指針數組:

  1 void (*funcArray[N])(void);

函數指針的一個用法出現在菜單驅動系統中。例如程序可以提示用戶輸入一個整數值來選擇菜單中的一個選項。用戶的選擇可以做函數指針數組的下標,而數組中的指針可以用來調用函數。下面是一個程序示例:

  1 #include <stdio.h>
  2 void func1()
  3 {
  4     printf("void func1()\n");
  5 }
  6 void func2()
  7 {
  8     printf("void func2()\n");
  9 }
 10 void func3()
 11 {
 12     printf("void func3()\n");
 13 }
 14 
 15 int main(void)
 16 {
 17     int i = 0;
 18     void (*p[3])(void) = {func1,func2,func3};
 19     for(;i<3;i++)
 20         (p[i])();
 21     return 0;
 22 }
 23 
 24 

6.拓展

  1 (*(void(*) ()) 0)()

思考以上代碼的意義!

(C/C++學習)16.函數指針