函數指針,指針函數,函數指針數組
這是一個群友發(fā)的筆試題目,里面涉及的東西也比較有意思。
直接看代碼
void (*f[])(char *)
這個是個什么東西?
我們先看看下面的東西
函數指針和指針函數的定義
我們看個代碼
int *func(int a,int b)
我們之前說過運算符的優(yōu)先級,「 * 」 的優(yōu)先級低于「( 」
由于「 * 」的優(yōu)先級低于「 () 」的優(yōu)先級,因而func首先和后面的「 () 」結合,也就意味著,func是一個函數。即:
int *(func)(int a,int b)
然后這個函數的返回值的類型是「 int * 」 即:指向int類型的指針
然后我們這樣修改上面的代碼
int (*func)(int a,int b)
「(*func) 」說明func是一個指針,然后后面跟著「()」說明這個指針指向一個函數,即指向函數的指針。
所以
函數指針: 首先是一個指針,這個指針指向一個函數
指針函數:首先是一個函數,這個函數的返回值一個指針
用typedef聲明一個函數指針
我們聲明一個函數指針,正常方法是
int (*pfunc)(int a,int b)
當我們命名很多個函數指針的時候,用上面的方法顯得非常不方便,所以我們可以這樣做
typedef int (*PF) (int a,intb)
PF pfunc;
例程:
#include "stdio.h"
typedef int(*PF)(int, int);
int add(int a, int b)
{
return a + b;
}
int reduce(int a, int b)
{
return a - b;
}
int main()
{
PF pfunc = NULL;
pfunc = add;
printf("add:%d\n",pfunc(3, 4));
pfunc = reduce;
printf("reduce:%d\n", pfunc(3, 4));
/*getchar是用VS編寫方便查看輸出*/
getchar();
return 0;
}
再說回上面的那個題目
void (*f[])(char *)
f 是個什么鬼東西了?
[] 的優(yōu)先級 比 *的優(yōu)先級高,所以 f首先是修飾了數組,然后跟后面的 *組合,就說明這個數組里面住的都是 指針,這些指針是什么呢,再出來看看就看到了,這個指針是 一個函數,這個函數的 參數是 char *返回值是void。
示例代碼
#include <stdio.h>
void (*f[3])(char *);
void efunction(char * s)
{
printf("%s\n",s);
}
int main()
{
f[0] = efunction;
//void (*f[])(char *) = {efunction};
(*f[0])("hello code");
return 0;
}
代碼輸出
hello code
--------------------------------
Process exited after 0.08441 seconds with return value 0
請按任意鍵繼續(xù). . .
函數指針在項目總的實際應用
這是我的android項目hal部分的代碼,這部分代碼用到的是函數指針,通過name來調用不同的函數。
懂了這些,我們就可以看懂別人的代碼了
我們有時候看別人的代碼時候,經常是一面懵逼,比如下面這個void (*p)(); 還有這個(*(void(*) ())0)();
我記得我在以前的文章里面有談到一個右左原則,從p開始看,往右走直到遇到)再往左走遇到(,(*p)我們就可以看出p是一個指針,繼續(xù)分析往右走,遇到(),說明p指向一個(void)的函數,往左走,知道p指向的函數返回值是void。
ok,看下面的例子。
#include "stdio.h"
void Function()
{
printf("Call Function!\n");
}
int main()
{
void(*p)();
*(int*)&p = (int)Function;
(*p)();
getchar();
return 0;
}
然后繼續(xù)分析(*(void(*) ())0)();
-
1、 void (*)()我們上面分析了這個是一個函數指針,只是把p去掉了而已。 -
2、把上面的 void (*)()用PN代替,上面的表達式變成(*(PN)0)();PN后面有一個0,這個是讓我們咋舌的地方,然后我們向一下(char)a;這樣的表達式,所以*(PN)0就是把0當成一個地址,強制轉換為PN類型,用*這個鑰匙取出這個地址區(qū)域的值。 -
3、把 (*(PN)0)()替換成PM,原來的表達式變成PM(),這樣大家看起來比較容易了吧,就是正常的函數調用。
給個例子自己去參透一下
#include <stdio.h>
#include <string.h>
char * fun1(char * p)
{
printf("%s\n", p);
return p;
}
char * fun2(char * p)
{
printf("%s\n", p);
return p;
}
char * fun3(char * p)
{
printf("%s\n", p);
return p;
}
int main()
{
char * (*pf[3])(char * p);
pf[0] = fun1; // 可以直接用函數名
pf[1] = &fun2; // 可以用函數名加上取地址符
pf[2] = &fun3;
pf[0]("fun1");
pf[0]("fun2");
pf[0]("fun3");
getchar();
return 0;
}
免責聲明:本文內容由21ic獲得授權后發(fā)布,版權歸原作者所有,本平臺僅提供信息存儲服務。文章僅代表作者個人觀點,不代表本平臺立場,如有問題,請聯系我們,謝謝!





