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