函式指針

函式指針

函式指針是指向函式的指針變數。 因此“函式指針”本身首先應是指針變數,只不過該指針變數指向函式。這正如用指針變數可指向整型變數、字元型、數組一樣,這裡是指向函式。如前所述,C在編譯時,每一個函式都有一個入口地址,該入口地址就是函式指針所指向的地址。有了指向函式的指針變數後,可用該指針變數調用函式,就如同用指針變數可引用其他類型變數一樣,在這些概念上是大體一致的。函式指針有兩個用途:調用函式和做函式的參數

基本介紹

  • 中文名:函式指針
  • 外文名:Function pointer
  • 解釋:指向函式的指針變數
  • 行業:IT
方法,對比區別,指針數組,定義,賦值,

方法

函式指針的聲明方法為:
返回值類型 ( * 指針變數名) ([形參列表]);
注1:“返回值類型”說明函式的返回類型,“(指針變數名 )”中的括弧不能省,括弧改變了運算符的優先權。若省略整體則成為一個函式說明,說明了一個返回的數據類型是指針的函式,後面的“形參列表”表示指針變數指向的函式所帶的參數列表。例如:
int func(int x); /* 聲明一個函式 */
int (*f) (int x); /* 聲明一個函式指針 */
f=func; /* 將func函式的首地址賦給指針f */
或者使用下面的方法將函式地址賦給函式指針:
f = &func;
賦值時函式func不帶括弧,也不帶參數,由於func代表函式的首地址,因此經過賦值以後,指針f就指向函式func(x)的代碼的首地址。
注2:函式括弧中的形參可有可無,視情況而定
下面的程式說明了函式指針調用函式的方法:
例一、
#include<stdio.h>int max(int x,int y){return (x>y? x:y);}int main(){    int (*ptr)(int, int);    int a, b, c;    ptr = max;    scanf("%d%d", &a, &b);    c = (*ptr)(a,b);    printf("a=%d, b=%d, max=%d", a, b, c);    return 0;}
ptr是指向函式的指針變數,所以可把函式max()賦給ptr作為ptr的值,即把max()的入口地址賦給ptr,以後就可以用ptr來調用該函式,實際上ptr和max都指向同一個入口地址,不同就是ptr是一個指針變數,不像函式名稱那樣是死的,它可以指向任何函式,就看你想怎么做了。在程式中把哪個函式的地址賦給它,它就指向哪個函式。而後用指針變數調用它,因此可以先後指向不同的函式。不過注意,指向函式的指針變數沒有++和--運算,用時要小心。
不過,在某些編譯器中這是不能通過的。這個例子的補充如下。
應該是這樣的:
1.定義函式指針類型:
typedef int (*fun_ptr)(int,int);
2.聲明變數,賦值:
fun_ptr max_func=max;
也就是說,賦給函式指針的函式應該和函式指針所指的函式原型是一致的。
例二、
#include<stdio.h>void FileFunc(){printf("FileFunc\n");}void EditFunc(){printf("EditFunc\n");}void main(){typedef void(*funcp)();funcp pfun=FileFunc;pfun();pfun=EditFunc;pfun();}

對比區別

指針函式函式指針的區別:
1,這兩個概念都是簡稱,指針函式是指返回值是指針的函式,即本質是一個函式。我們知道函式都有返回類型(如果不返回值,則為無值型),只不過指針函式返回類型是某一類型的指針。
其定義格式如下所示:
返回類型標識符*函式名稱(形式參數表)
返回類型可以是任何基本類型和複合類型。返回指針的函式的用途十分廣泛。事實上,每一個函式,即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當於一個指針。比如函式返回一個整型值,實際上也相當於返回一個指針變數的值,不過這時的變數是函式本身而已,而整個函式相當於一個“變數”。例如下面一個返回指針函式的例子:
//指針函式是指返回值是指針的函式,即本質是一個函式:#include<iostream>using namespace std;int main(){float*find(float(*p)[4],int m);//查詢序號為m的學生的四門課程的成績float score[][4]={{50,51,52,55},{70,70,40,80},{77,99,88,67}};//定義成績數組,第一維可以為變數float*pf=NULL;//定義一個指針時一定要初始化int i,m;cout<<"請輸入您想查詢的學生的序號:";cin>>m;pf=find(score,m);//返回為一維數組指針,指向一個學生成績for(i=0;i<4;i++)cout<<*(pf+i)<<"";cout<<endl;return 0;}float *find(float(*p)[4],int m){float *pf=NULL;pf=*(p+m);//p是指向二維數組的指針,加*取一維數組的指針return pf;}
學生學號從0號算起,函式find()被定義為指針函式,其形參pointer是指針指向包含4個元素的一維數組指針變數。pf是一個指針變數,它指向浮點型變數。main()函式中調用find()函式,將score數組的首地址傳給pointer.

指針數組

定義

關於函式指針數組的定義方法,有兩種:一種是標準的方法;一種是矇騙法。
第一種,標準方法:
{
分析:函式指針數組是一個其元素是函式指針的數組。那么也就是說,此數據結構是一個數組,且其元素是一個指向函式入口地址的指針。
根據分析:首先說明是一個數組:數組名[]
其次,要說明其元素的數據類型指針:*數組名[].
再次,要明確這每一個數組元素是指向函式入口地址的指針:函式返回值類型 (*數組名[])().請注意,這裡為什麼要把“*數組名[]”用括弧擴起來呢?因為圓括弧和數組說明符的優先權是等同的,如果不用圓括弧把指針數組說明表達式擴起來,根據圓括弧和方括弧的結合方向,那么 *數組名[]() 說明的是什麼呢?是元素返回值類型為指針的函式數組。有這樣的函式數組嗎?不知道。所以必須括起來,以保證數組的每一個元素是指針。
}
第二種,矇騙法:
儘管函式不是變數,但它在記憶體中仍有其物理地址,該地址能夠賦給指針變數。獲取函式地址的方法是:用不帶有括弧和參數的函式名得到。
函式名相當於一個指向其函式入口指針常量。 那么既然函式名是一個指針常量,那么就可以對其進行一些相應的處理,如強制類型轉換
那么我們就可以把這個地址放在一個整形指針數組中,然後作為函式指針調用即可。
完整例子:
#include <stdio.h>int add1(int a1,int b1);int add2(int a2,int b2);int main(void){    int numa1 = 1, numb1 = 2;    int numa2 = 2, numb2 = 3;    int(*op[2])(int a,int b);        op[0] = add1;    op[1] = add2;        printf("%d%d\n", op[0](numa1, numb1), op[1](numa2, numb2));}int add1(int a1,int b1){    return a1 + b1;}int add2(int a2,int b2){    return a2 + b2;}

賦值

為函式指針數組賦值有兩種方式:靜態定義和動態賦值。
1. 靜態定義
在定義函式指針數組的時候,已經確定了每個成員所對應的函式。例如:
void(*Array[])(void)={Stop,Run,Jump};
從根本上講函式指針數組依然是數組,所以和數組的定義類似,由於是靜態賦值,[ ]裡面的數字可以
省略。這個函式指針數組的成員有三個。
  Array[1]();//執行Run函式
2. 動態賦值
也可以先定義一個函式指針數組,在需要的時候為其賦值。為了還原其本來面目,我們先對這個執行特定類型的函式指針進行類型重定義,然後再用這個新數據類型來定義數組。如下:
typedef void(*Funcint)(void);//此類型的函式指針指向的是無參、無返回值的函式。 Funcint Array[32];//定義一個函式指針數組,其每個成員為Funcint類型的函式指針    Array[10]=INT_TIMER0;//為其賦值    Array[10]();//調用函式指針數組的第11個成員指向的函式

相關詞條

熱門詞條

聯絡我們