#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);
}