首先,我們先要明确一點,函數指針是一個指針,隻不過這個指針指向的對象有些特殊,是一個函數。指針函數是一個函數,隻不過函數的傳回值是一個指針。
一、指針函數,指針函數的一般定義格式是:
類型* 函數名(形參清單)
{
語句塊;
return 傳回值;
}
舉個例子如下:
#include <stdio.h>
#include <string.h>
char* fun(char p[],int n)
{
char *buf;
buf = p;
return buf;
}
int main()
{
char str[]="pointer";
printf("%s",fun(str,strlen(str)));
return 0;
}
編譯及運作結果如下
二、函數指針
1.函數指針的定義格式:
傳回類型 (*函數指針名)(形參類型清單);//注:可以沒有形參類型清單,但要有 () 表示形參類型及個數在指派時決定
例如:int (*fun)(int); 這就定義了一個指向傳回值為int型,形參為int型的函數的函數指針 fun。
2.函數指針的指派:
有這麼一個和fun指針比對的函數fun1,那麼它的指派為:fun = fun1;
int fun1(int n)
{
printf("%d\n",n);
return 0;
}
3.函數指針的一個應用是回調函數,下面我們定義倆個不同的.cpp檔案,實作一個回調函數
第一個檔案fs.cpp
/*NULL的頭檔案*/
#include <stddef.h>
extern int fun1(int n);
int(*g_funp)(int)=NULL;
int fun(int(*funp)(int n))
{
fun1(100);
g_funp = funp;
return 0;
}
第二個檔案test.cpp
#include <stdio.h>
#include <string.h>
/*回調函數*/
extern int fun(int (*funp)(int n));
int fun1(int n)
{
printf("%d\n",n);
return 0;
}
int main()
{
fun(fun1);
return 0;
}
編譯及運作結果如下:
程式分析:
main函數調用fun函數,并傳遞一個函數指針fun1,在fun函數中又去回調fun1函數,其中在fs.cpp檔案中又定義了一個函數指針g_funp,并在fun中将傳過來的參數指派給它,目的是以後能在fs.cpp中其他函數中調用這個fun1(當然這個是在fun1定義成static時的一種處理,fun1如果沒有定義成static時直接使用extern聲明調用即可),一般函數指針在linux中的寫法常是被封裝成結構體的一個成員,然後在傳參的時候把整個結構體傳過去,接着再去處理函數指針這個成員。
4.函數指針的另一個應用,函數指針數組
對于有多個函數調用時,正常我們會通過輸入的編号結合switch case去調用對應的函數,那麼當函數個數十分龐大時就 使用switch case的效率就十分低了,為此我們引入函數指針數組
舉個例子如下:
#include <stdio.h>
int add(int a,int b)
{
return a+b;
}
int dec(int a,int b)
{
return a-b;
}
int seq(int a)
{
return a*a;
}
int main()
{
/*因為函數的參數個數既有一個的也有倆個的是以定義成()這種形式*/
int (*funparry[3])()={add,dec,seq};
int i=0,data1=0,data2=0,ret;
while(1)
{
printf("0. add\n");
printf("1. dec\n");
printf("2. seq\n");
printf("select number\n");
scanf("%d",&i);
if(i==2)
{
printf("input data1\n");
scanf("%d",&data1);
ret = funparry[i](data1);
}
else
{
printf("input data1 and data2\n");
scanf("%d %d",&data1,&data2);
ret = funparry[i](data1,data2);
}
printf("result is %d\n",ret);
}
return 0;
}
執行結果如下: