函數指針的聲明方法爲:
注1:“函數類型”說明函數的返回類型,由於“()”的優先級高於“*”,所以指針變量名外的括號必不可少,後面的“形參列表”表示指針變量指向的函數所帶的參數列表。例如:
int func(int x); /* 聲明一個函數 */
int (*f) (int x); /* 聲明一個函數指針 */
f=func; /* 將func函數的首地址賦給指針f */
賦值時函數func不帶括號,也不帶參數,由於func代表函數的首地址,因此經過賦值以後,指針f就指向函數func(x)的代碼的首地址。
注2:函數括號中的形參可有可無,視情況而定。
下面的程序說明了函數指針調用函數的方法:
例一、
#include<stdio.h>
int max(int x,int y){ return(x>y?x:y); }
void 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);
}
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=FileFunc;
(*funcp)();
funcp=EditFunc;
(*funcp)();
}
編輯本段指針函數和函數指針的區別
1,這兩個概念都是簡稱,指針函數是指帶指針的函數,即本質是一個函數。我們知道函數都又有返回類型(如果不返回值,則爲無值型),只不過指針函數返回類型是某一類型的指針。
其定義格式如下所示:
返回類型標識符 *返回名稱(形式參數表)
{ 函數體 }
返回類型可以是任何基本類型和複合類型。返回指針的函數的用途十分廣泛。事實上,每一個函數,即使它不帶有返回某種類型的指針,它本身都有一個入口地址,該地址相當於一個指針。比如函數返回一個整型值,實際上也相當於返回一個指針變量的值,不過這時的變量是函數本身而已,而整個函數相當於一個“變量”。例如下面一個返回指針函數的例子:
#include<iostream>
using namespace std;
void main()
{
float *find(float(*pionter)[4],int n);
static float score[][4]={{60,70,80,90},{56,89,34,45},{34,23,56,45}};
float *p;
int i,m;
cout<<"Enter the number to be found:";
cin>>m;
p=find(score,m);
for(i=0;i<4;i++)
cout<<" "<<*(p+i);
}
float *find(float(*pionter)[4],int n)/*定義指針函數*/
{
float *pt;
pt=*(pionter+n);
return(pt);
}
學生學號從0號算起,函數find()被定義爲指針函數,起形參pointer是指針指向包含4個元素的一維數組的指針變量。pointer+1指向 score的第一行。*(pointer+1)指向第一行的第0個元素。pt是一個指針變量,它指向浮點型變量。main()函數中調用find()函數,將score數組的首地址傳給pointer.
2,“函數指針”是指向函數的指針變量,因而“函數指針”本身首先應是指針變量,只不過該指針變量指向函數。這正如用指針變量可指向整型變量、字符型、數組一樣,這裏是指向函數。如前所述,C在編譯時,每一個函數都有一個入口地址,該入口地址就是函數指針所指向的地址。有了指向函數的指針變量後,可用該指針變量調用函數,就如同用指針變量可引用其他類型變量一樣,在這些概念上一致的。函數指針有兩個用途:調用函數和做函數的參數。
編輯本段關於函數指針數組的定義
關於函數指針數組的定義方法,有兩種:一種是標準的方法;一種是矇騙法。
第一種,標準方法:
{
分析:函數指針數組是一個其元素是函數指針的數組。那麼也就是說,此數據結構是一個數組,且其元素是一個指向函數入口地址的指針。
根據分析:首先說明是一個數組:數組名[]
其次,要說明其元素的數據類型指針:*數組名[].
再次,要明確這每一個數組元素是指向函數入口地址的指針:函數返回值類型 (*數組名[])().請注意,這裏爲什麼要把“*數組名[]”用括號擴起來呢?因爲圓括號和數組說明符的優先級是等同的,如果不用圓括號把指針數組說明表達式擴起來,根據圓括號和方括號的結合方向,那麼 *數組名[]() 說明的是什麼呢?是元素返回值類型爲指針的函數數組。有這樣的函數數祖嗎?不知道。所以必須括起來,以保證數組的每一個元素是指針。
}
第二種,矇騙法:
儘管函數不是變量,但它在內存中仍有其物理地址,該地址能夠賦給指針變量。獲取函數地址的方法是:用不帶有括號和參數的函數名得到。
函數名相當於一個指向其函數入口指針常量。那麼既然函數名是一個指針常量,那麼就可以對其進行一些相應的處理,如強制類型轉換。
那麼我們就可以把這個地址放在一個整形指針數組中,然後作爲函數指針調用即可。
完整例子:
#include "stdio.h"
int add1(int a1,int b1);
int add2(int a2,int b2);
void main()
{
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;
}