c中函數指針的使用

  在C/C++中存在着函數指針,即指向函數的指針。我目前已知的兩種使用方法是:


  



#include <string.h>  
#include <stdio.h>  
typedef int* PINNT;  
#define PP int*  
  
int funcA(int a,int b);  
int funcB(int* a,int *b);  
int  main(int argc, char *argv[])  
{  
    int (*func)(int,int);  
    //func = &funcA;  
    func = funcA;  
    //兩種賦值給函數指針的方法都可以  
    printf("%d",func(1,10));  
    //printf("%d",(*func)(1,10));  
    //兩種調用函數指針的方法都可以  
    //兩種賦值方法和兩種調用方法可以任選一種組合  
      
}  
  
int funcA(int a,int b)  
{  
    return a + b;  
}  
  
int funcB(int* a,int *b)  
{  
    (*a) = (*a) + (*b);  
    return 1;  
}  


 


這裏int (*func)(int,int)定義了一個函數指針變量,可以接受函數名或者函數名的指針(這裏我還沒有很清楚)。


 


然後我在CSDN上面找到了一個例子,據說是華爲的面試題目,代碼如下,這時程序正常輸出值爲110。



#include <stdio.h>   
int   inc(int   a)   
{   
    return(++a);   
}   
  
int   multi(int*a,int*b,int*c)   
{   
    return(*c=*a**b);   
}   
  
typedef   int(FUNC1)(int);   
typedef   int(FUNC2)(int*,int*,int*);   
  
void   show(FUNC2   fun,int   arg1,   int*arg2)   
{   
    FUNC1   *p = &inc;   
    int   temp   =p(arg1);   
    fun(&temp,&arg1,   arg2);   
    printf( "%d\n ",*arg2);   
}   
  
main()   
{   
    int   a;   
    show(multi,10,&a);   
    getchar();   
    return   0;   
}  
一開始我沒有理解這個用法的時候,以爲這裏使用的方法與方法一相同,故直接寫成





typedef   int(FUNC1)(int);   
typedef   int(FUNC2)(int*,int*,int*);   
  
void   show(FUNC2   fun,int   arg1,   int*arg2)   
{   
    FUNC1  = inc;   
    int   temp   =p(arg1);   
    fun(&temp,&arg1,   arg2);   
    printf( "%d\n ",*arg2);   
}   


這時候,編譯器給出的提示是:


1>d:\vctest\test4\test4\test4.c(17) : error C2513: 'int (int)' : no variable declared before '=' 


FUNC1 = inc這個語句的左邊沒有變量被申明,這個錯誤提示說明利一點:FUNC是一種類型而不是一個變量。做出如下更正:


 



FUNC1  *p = inc;   


程序正確,更加證明了


[cpp] view plain copy
typedef   int(FUNC1)(int);   
typedef   int(FUNC2)(int*,int*,int*);   
語句定義了兩個自己的數據類型FUNC1和FUNC2,這兩個類型申明的變量用保存函數指針


 


 也可以採用下面的方式進行定義:



typedef   int (*FUNC1)(int);   
typedef   int (FUNC2)(int*,int*,int*);   
  
void   show(FUNC2   fun,int   arg1,   int*arg2)   
{   
    FUNC1  p = inc;   
    int   temp   = p(arg1);   
    fun(&temp,&arg1,   arg2);   
    printf( "%d\n ",*arg2);   
}   
   
 


以上例子,涉及到的概念有函數指針,函數類型和函數指針變量


函數指針變量有兩種實現方法:


    1. 先申明函數指針類型,在用函數指針類型申明函數指針變量


    //typedef void FunType(int);  -- FunType:同樣是一個函數指針類型。



typedef void (*PF)(int,int);  
//使用函數指針類型申明的變量就是函數指針變量  
//PF a = &inc//PF a = inc  
    2. 直接定義一個函數指針變量


 



void (*fPV)(int,int);  
fvp  = inc // fvp = &inc  


函數類型與函數指針變量


    如何定義函數類型呢


   



typedef void (FT)(int,int);  
    申明的函數類型如何使用呢?


 


首先可以用來申明函數:


FT x,y等價於:


void x(int,int);


void y(int,int);


請看如下的示例:



#include <stdio.h>   
  
typedef int (FT)(int*,int*);  
FT x,y;  
  
  
main()   
{   
    int a = 1,b=2;  
    x(&a,&b);  
    (*y)(&a,&b);  
}  
  
int x(int* a,int*b){  
    *a = *a + *b;  
    printf("%d\n",*a);  
}  
  
int y(int*a,int* b){  
    *a = *a * (*b);  
    printf("%d\n",*a);  
}  


 


上面的程序輸出3和6


 



#include <stdio.h>   
  
typedef int (FT)(int*,int*);  
FT x,y,*z,u;  
  
  
main()   
{   
    int a = 1,b=2;  
    x(&a,&b);  
    (*y)(&a,&b);  
    z = x;//這裏x是一個函數名,但是編譯器會把函數名轉換爲函數指針變量,所以也可以顯式寫成z = &x;  
    x(&a,&b);  
    //u = x;//這裏出錯了這裏u是一個函數名稱,是一個指針常量,類似於數組名稱,是不能夠被賦值的  
}  
  
int x(int* a,int*b){  
    *a = *a + *b;  
    printf("%d\n",*a);  
}  
  
int y(int*a,int* b){  
    *a = *a * (*b);  
    printf("%d\n",*a);  
}  


上面的例子中FT *Z其實是申明瞭一個指向函數的函數指針變量,類似於int(*z)(int*,int*)。


 


最後再來看下那個困擾了我很久的例子吧:


#include <stdio.h>   
int   inc(int   a)   
{   
    return(++a);   
}   
  
int   multi(int*a,int*b,int*c)   
{   
    return(*c=*a**b);   
}   
  
typedef   int (*FUNC1)(int);   
typedef   int (FUNC2)(int*,int*,int*);   
typedef   int (FUNC3)(int*,int*,int*);   
  
void   show(FUNC2 *fun,int   arg1,   int*arg2)   
//void   show(FUNC2 fun,int   arg1,   int*arg2)//這裏做這樣的聲明也一樣是對的   
{   
    FUNC1  p = &inc;   
    FUNC2 *q = multi;  
    int   temp   = (*p)(arg1);   
    (*fun)(&temp,&arg1,   arg2);  
    //fun(&temp,&arg1,   arg2); //這裏的兩種調用方法和上面的惡兩種聲明方法可以任意組合,,原因是函數名和函數指針常量的隱式轉換  
    printf( "%d\n ",*arg2);   
}   
  
main()   
{   
    int   a;   
    show(multi,1,&a);   
    getchar();   
    return   0;   
}  
最讓我疑惑的是


void   show(FUNC2 *fun,int   arg1,   int*arg2) 
//void   show(FUNC2 fun,int   arg1,   int*arg2)//這裏做這樣的聲明也一樣是對的


這兩種聲明方式都是對的,採用void   show(FUNC2 fun,int   arg1,   int*arg2)//這裏做這樣的聲明也一樣是對的這種方式聲明, show(multi,1,&a);調用時正確的,


而前面的代碼中,我也說過//u = x;//這裏出錯了這裏u是一個函數名稱,是一個指針常量,類似於數組名稱,是不能夠被賦值的, 這個問題困擾我很久啊,仔細考慮之後,我個人的觀點是:void   show(FUNC2 fun,int   arg1,   int*arg2)使用一個函數做爲形式參數,調用時傳遞一個函數名字給他就可以,也可以傳遞一個函數常量指針。類比於使用指針常量或者數組作函數書參數的時候



#include <stdio.h>   
  
typedef void (FT)(int* const a);  
FT z;  
void main()  
{  
    int a[]={1,2,3,4,5};  
    int b = 5;  
    int *c = &b;  
    z(a);  
    //但是如果在這裏給a = c是不對的  
}  
  
void z(int* const a)  
{  
    printf("%d",*a);  
}  
 



發佈了21 篇原創文章 · 獲贊 33 · 訪問量 7萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章