不知不覺,指針解析來到了第三篇。本篇想講的內容是有點高級,也有晦澀。說到高級和晦澀,有些人就不同意了。不就些基礎內容嘛,何必用高級一次呢?我想我是假借高級一詞,重點在“有點”。我倒不能說有點猥瑣,有點惡心吧。
我們都知道,程序中的每個函數都位於內存的某個位置上,所以就存在指向那個位置上的指針。知道了這個道理之后呢,我們來看看以下這些聲明是怎么一回事?
int f; // 整型變量,這個鬼都知道
int *f; // 一個指向整型的指針,這個鬼也知道
int f(); // 返回類型為整型的函數
int *f(); // 返回類型為一個指向整型指針的函數
// 以上都很平常,都是正常情況
int (*f)(); // 這是神馬?.....這是函數指針,一個返回類型為整型的,不接受輸入參數的函數指針
int *(*f)(); // 這個也是函數指針,一個返回類型為指向整型指針的,不接受輸入參數的函數指針
int (*f[])(); // 這個有點暈!這是一個數組,其元素是函數指針
int *(*f[])(); // 這也是一個數組,其元素也是函數指針,只是返回類型和上面不一樣
指針真是強大,傷不起!
看過上面的聲明之后,我們可以進入函數指針的世界了。現在展示一個函數指針最基本的調用:
#include <stdio.h>
void MyFun(int ); // 要調用的函數聲明
void (*FunP)(int ); // 聲明的函數指針,接受一個int類型的參數,返回值為空的函數指針
int main(int argc, char* argv[])
{
MyFun(1); // 這里將直接調用MyFun函數
FunP = &MyFun; // 將MyFun函數的地址賦給FunP,其實,FunP = MyFun,也可以,好玩吧。
(*FunP)(2); // 這里通過函數指針FunP”變量“來調用MyFun函數,注意變量兩字啊。
FunP(3); // 你可以這樣調用
}
void MyFun(int x)
{
printf("%d\n",x);
}
最近我發覺,有些東西還是直接貼代碼好。不然真不知道怎么表達?囧啊!以上的調用過程顯示了函數指針的奧妙啊。基於上面的思路,我們在進行拓展
。我們都知道typedef這個參數,其作用是聲明自定義數據類型,配合各種原有數據類型來達到簡化編程的目的的類型定義關鍵字。例如:
typedef char data_type;
這個可幫了大忙了。我修改數據類型之類的,都可以灰常快速的進行。那時牽一發而動全身啊!當然,我現在不說它神馬牽一發而動全身的問題。我想讓大家看懂下面這個問題:
typedef int (*Pfun) (const char *, const char *); // 這個看起來有點暈吧!
施主莫暈!這樣只是定義一個函數指針類型,莫怕莫怕!這個聲明引入了 Pfun 類型作為函數指針的同義字,該函數有兩個 const char * 類型的參數以及一個 int 類型的返回值。當你適應了這個之后,我想介紹回調函數了。神馬是回調函數?用戶把一個函數指針做為一個參數傳遞給其他函數,后者將“回調”用戶的函數。尼瑪,這個解釋夠拗口的!直白點就是說與指針函數一致的函數可以通過這個回調動作,讓其他函數使用!這個還是有點拗口!
看了下面這個例子就會好多:
#include <stdio.h>
int CompareImpl(void const *a, void const *b ); // 要調用的函數聲明
typedef int (*Compare) (void const *, void const *); // 聲明的函數指針,接受一個void類型的指針參數,返回值為整型的函數指針
int Equal(int , int , Compare); // 回調函數的入口是Compare,至於怎么Compare那就要看傳入的函數是如何了。
int main(int argc, char* argv[])
{
printf("結果為:%d\n", Equal(1, 2, CompareImpl)); // 這里我們傳入了CompareImpl,說明在*這個地方時調用CompareImpl函數來進行比較
return 0;
}
int CompareImpl(void const *a, void const *b )
{
if (*(int *)a == *(int *)b) // 這里很好玩,我們將void指針轉換成int類型。這個函數就被我們改照成了接受
{
return 1;
}
else
{
return 0;
}
}
int Equal(int a, int b, Compare compare)
{
return compare(&a, &b); // *
}
以上的例子應該是最淺顯的回調解釋了。如果還是不明白,去翻翻書和放狗出去查查相關的資料了
。以上的compare讓大家想起神馬呢?我想說,這讓我想起了模板!用void指針和函數指針來模擬模板的一些初級功能!
接下來要說的是轉移表,這個號稱是switch/case殺手!到底怎么殺呢?看看一下的代碼對比就知道了:
switch ()
{
case A:
func1(1, 2);
break;
case B:
func2(1, 2);
break;
case C:
func3(1, 2);
break;
case D:
func4(1, 2);
break;
default:
break;
}
// 納尼,這么長!!
// 現在你可以用這樣來代替
void func1(double, double);
void func2(double, double);
void func3(double, double);
void func4(double, double);
void (*pfunc[])(double, double) =
{func1, func2, func3, func4 };
// 調用的時候
pfunc[1](1,2); // 調用的是func2(1, 2)
明眼人就看出來了,這是函數指針數組的應用了。
結了,就說到這里吧!睡覺了。。。。。
參考文獻
1. 《C語言程序設計》
2. 《C和指針》
3. 《C專家編程》
4. 百度百科的typdef的解釋。