第五十二章 指針(七)
「行了行了,老爹你也不用做鋪墊了,咱們開門見山直接說吧!大家都這么熟的人了,你這背后的套路早就我們看穿了。」
還不等老爹說完,我便揮手打斷了他。
「……」
老爹是一陣語塞,滿臉的無奈。
「這個時候,我們就可以使用typedef這個喜歡取名字的家伙來定義函數(shù)指針類型。注意到,這里是定義的一種數(shù)據(jù)類型,這意味著我們可以使用這種類型來聲明很多的變量,所以剛剛提到的問題也就迎刃而解了。具體的使用方法如下:
typedef int(*Func)(int,int);
int max(int a,int b)
{
return a > b ? a : b;
}
int min(int a, int b)
{
return a < b ? a : b;
}
int main(int argc, char const* argv[])
{
Func f_max = max;
Func f_min = min;
int maxValue = f_max(3, 4);
int minValue = f_min(3, 4);
}
看到?jīng)],因為使用了typedef,這個時候Func已經(jīng)不是某個具體的指針變量了,而是搖身一變,升級成為了開山鼻祖。
這樣一來,F(xiàn)unc就成了一種函數(shù)指針類型,可以用來聲明變量,所有返回值為int,有兩個int參數(shù)的函數(shù)都可以賦值給它的變量。
到這里,指針和函數(shù)之間那些不可告人的關系就被我們?nèi)棵噶恕!?p> 「可是老爹,你說了這么多,我也沒有明白函數(shù)指針有什么用啊,如果我們要調(diào)用一個函數(shù),直接用方法名調(diào)用不好么,何必這么麻煩?」
我不解道。
「嗯~,之前我跟你們說了,其實函數(shù)指針最大的用處是作為參數(shù)傳遞給另外一個函數(shù),這種就做回調(diào)機制,而作為參數(shù)傳遞的函數(shù)指針就被稱之為回調(diào)函數(shù)。
現(xiàn)在我們就用一個貼近生活的小案例來說明回調(diào)函數(shù)。
假設我們住這個小區(qū)是非常高檔的小區(qū),甚至都和國際接軌了,里面除了中國人以外還居住了很多外國友人。
物業(yè)為了提高服務水品,于是要求保安叔叔們在小區(qū)門口和每一個進來小區(qū)的業(yè)主敬禮問好。
那現(xiàn)在問題就來了,敬禮還好,不管是中國人還是外國人都能夠看懂。但是問好因為語言的差異性,會存在問題。如果說中文的話,大部分外國人聽不懂,但是如果說英語的話,大部分中國人也聽不懂。
于是啊,有個聰明的保安想出了一種讓人拍案叫絕的辦法,讓進出的人自己選擇問好的方式,這樣一來,中國人問好用漢語,外國人問好用英語。
吶,上面的場景就可以用回調(diào)函數(shù)來實現(xiàn):
typedef void (*Func)(void);
void chineseSayHello(void)
{
printf(“歡迎回家“);
}
void othersSayHello(void)
{
printf(“welecome go back home“);
}
void sayHello(Func f_sayHello)
{
/*敬禮*/
f_sayHello();
}
這樣,當中國人進入小區(qū)的時候,咱們就把chineseSayHello這個函數(shù)作為參數(shù)傳遞給sayHello,到時候保安叔叔們就會說『歡迎回家』,而如果是外國人,就把othersSayHello作為參數(shù)傳遞給sayHello,這樣保安叔叔們就會說『welecome go back home』。
其實我們之前在寫推箱子這個游戲時,講到的響應事件,追根究底其實就是使用的回調(diào)函數(shù)機制。
通過上面的案例,我們可以總結出一點,當我們需要在一個函數(shù)中執(zhí)行某些操作,但是這些操作的具體內(nèi)容在實現(xiàn)函數(shù)的時候不能確定,那么這個時候我們就可以考慮使用回調(diào)函數(shù)了。
當然了,就這么三言兩語就想讓你們理解回調(diào)機制無疑是太想當然了,等到你們在實際開發(fā)過程中會接觸到的?!?p> 看著我和小弦子臉上毫不掩飾的茫然,老爹不置可否地聳了聳肩。
「現(xiàn)在指針的內(nèi)容就剩下最后一點點了——多重指針和指針數(shù)組。這兩個知識點用到的時候比較少,咱們點到為止即可。
我們先說指針數(shù)組,既然指針是一種數(shù)據(jù)類型,那么它有數(shù)組也不是什么怪事,那你們說說,指針數(shù)組是個嘛玩意?」
「一個口袋,里面裝的全部都是指針!」
我和小弦子異口同聲道。
「冰狗,回答正確!那么再請你們大膽的猜想一下,如何定義一個指針數(shù)組。」
聞言后,我先總結了一下普通數(shù)據(jù)類型聲明數(shù)組的方式,然后依葫蘆畫瓢寫出了自己的答案,沒想到居然還被我蒙對了。
「其實指針數(shù)組從你們寫下第一行代碼的時候就見到了哦!而且在這之后,你們每次寫代碼的時候指針數(shù)組都默默地陪伴在你們身邊。它認識你們,你們卻不認識它?!?p> 這個時候,老爹突然神秘地笑了笑。
「寫下第一行代碼的時候就見到了指針數(shù)組這么高深的知識?不可能啊,寫的第一段代碼分明是一個輸出『hello world』的程序嘛。
等等,老爹后面這句話分明是別有所指嘛?!?p> 我在心里暗自揣摩了一下老爹的話,最終推斷出只有main函數(shù)才滿足老爹的這個說法。
因為main函數(shù)從我們開始寫第一段代碼到之后的每次寫代碼都會用到它,那么指針數(shù)組出現(xiàn)的位置就呼之欲出了,只能是main函數(shù)的參數(shù)!
關于main函數(shù),一開始老爹也沒有給我解釋太多,只是說這是程序的入口地址,所有程序都是從main函數(shù)開始執(zhí)行的,讓我給硬背下來。
main函數(shù)的第一個參數(shù)是argc,int類型的變量,第二個參數(shù)是argv,指數(shù)組參數(shù)就只能是它了。
「看來你們已經(jīng)猜到了,那我們今天就順帶來揭開main函數(shù)什么的面紗,現(xiàn)在我們寫一段代碼來運行一下:
int main(int argc, char const *argv[])
{
for (int i = 0; i < argc; i++)
{
printf(“argv[%d]=%s\n“, i, argv[i]);
}
getchar();
return 0;
}
在小黑屏里面運行可執(zhí)行文件的時候,咱們在后面加點東西,程序編譯出來的可執(zhí)行文件名字叫point.exe,那小黑屏就執(zhí)行這個:
pointer.exe hello world Java」
按照老爹說法,在小黑屏里面輸出了:
argv[0]= pointer.exe
argv[1]= hello
argv[2]= world
argv[3]= Java
原來argv是一個字符指針數(shù)組,而字符指針就是一個字符串,所以argv是一個字符串數(shù)組,而argc是這個數(shù)組的長度!并且字符串數(shù)組的元素來自于我們運行程序時攜帶的參數(shù)!
哈哈,沒想到學到這里,居然才把main函數(shù)給弄清楚。難怪當初老爹不給我多講main函數(shù),因為講我的確也難以理解,說不定還會因此畏難而放棄學習。