摘要:回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發(fā)生時由另外的一方調用的,用于對該事件或條件進行響應。
上次我們學習了指針的相關知識,那么今天就讓我們進一步的深入去學習指針吧!
沒有看過上一篇關于與指針的相關知識是小伙伴可以點擊下面的鏈接跳轉哦~
不知道小伙伴們有沒有在查詢函數的時候,看到函數的形參列表或者返回類型中,出現了void* 這種類型?
例如:
void qsort (void* base, size_t num, size_t size, int (*compar)(const void*,const void*));
上面最后面就出現了void*,那么這個是什么呢?
這個不是空指針!
空指針的表示方法為:NULL
這種類型叫做無類型指針!
無類型指針意思就是沒有具體類型的指針,也就是說,你在函數傳參的時候,傳入什么指針類型都可以。
這種指針類型并不能直接對其進行解引用和運算,需要強制類型轉化為具體類型的指針才可以!
int main() { void* p;//定義了一個無類型指針變量p int n = 10; p = &n;//把整型變量n的地址賦值給p //printf("%d/n", *p);//這是錯誤的用法! //我們需要在解引用前把p強制類型轉化為int*類型才可以進引用! printf("%d/n", *(int*)p); return 0;}
在C語言中,除了內置的數據類型,我們還可以自定義數據類型。
結構體就是自定義類型的典型代表!下面就讓我們一起來學習結構體的指針吧!
代碼演示如下:
#include //簡單的定義了一個結構體類型struct Book { char name[20]; double price;};int main() { //用定義的結構體類型創(chuàng)建了一個變量book,并初始化 struct Book book = { "sanguoyanyi",25.5 }; //定義了一個結構體的指針變量,并把book的地址賦值給該結構體指針變量 struct Book* p = &book; //利用指針找到結構體變量 printf("%s/n", (*p).name); printf("%.2lf/n", p->price); return 0;}
上面演示了結構體指針變量的基本使用方式,關于結構體的相關知識,我們在這里就不展開啦,以后我們在去了解結構體。
我們還演示了結構體指針變量的兩種用法
- 解引用后再找到成員變量
- 直接指向成員變量
關于結構體指針變量的用法,有一個特別重要的應用場景哦~
那就是再調用函數需要再傳參時傳入結構體變量的話,我們一般采用的是傳入結構體變量的地址哦!
在C語言中,自定義類型除了結構體還有枚舉。
枚舉類型也有屬于自己的指針哦。
看下面代碼演示:
#include //定義了一個枚舉類型enum Day//星期{ Mon, Tues, Wed, Thur, Fri, Sat, Sun};int main() { //創(chuàng)建了一個枚舉變量 enum Day day = Mon; //創(chuàng)建了一個枚舉類型的指針 enum Day* p; //把枚舉變量的地址復制給枚舉類型的指針 p = &day; printf("%d/n", *p); return 0;}
上面的代碼就演示了枚舉類型的指針,但是由于我知識儲備不夠,沒有想到有什么應用場景,如果知道該如何使用的小伙伴可以在評論區(qū)告訴我哦~
不僅僅是變量擁有屬于自己的地址,就連函數也有地址哦!
我們先看一看下面的代碼演示:
#include void test(){printf("hehe/n");}int main(){printf("%p/n", test);printf("%p/n", &test);return 0;}
運行上面的代碼,我們會發(fā)現打印出來的兩個值是一樣的。
這也就說明
函數也有地址,而且函數名就代表著函數本身的地址!
我們該怎么樣創(chuàng)建函數的指針變量呢?
void test(){printf("hehe/n");}//下面pfun1和pfun2哪個有能力存放test函數的地址?void (*pfun1)();void *pfun2();
上面的代碼中,pfun1是指針變量,因為它先跟*結合,說明該變量是一個指針變量,前面的void說明了它指向的函數的返回類型為空,后面的(),表示這個它指向的函數的形參也為空
再看下面的栗子
我們再來看一個栗子:
#include //簡單定義了一個加法函數int Add(int x, int y) { return x + y;}int main() { //創(chuàng)建了兩個指針變量 int (*pfun1)(int, int); int (*pfun2)(int x, int y); //給兩個指針變量賦值 pfun1 = &Add; pfun2 = Add; //通過指針去調用函數,并打印返回值 printf("%d/n", (*pfun1)(3, 4)); printf("%d/n", pfun2(6, 7)); return 0;}
通過上面的栗子我們可以知道
- 創(chuàng)建函數指針變量時,后面形參列表的形參變量符號可以省略
- 給指針變量賦值的時候,函數名和&函數名的實際效果都一樣
- 函數指針調用函數的時候可以解引用,也可以直接通過指針變量名來調用函數
通過函數指針,我們就可以用來調用函數了。
回調函數就是一個通過函數指針調用的函數。
如果你把函數的指針(地址)作為參數傳遞給另一個函數,當這個指針被用來調用其所指向的函數時,我們就說這是回調函數。
回調函數不是由該函數的實現方直接調用,而是在特定的事件或條件發(fā)生時由另外的一方調用的,用于對該事件或條件進行響應。
其中,庫函數qsort的形參列表,就是使用了回調函數的方法哦!
有興趣的小伙伴也可以自己去研究一下這個庫函數,有時間的話,我也會分享一篇關于qsort函數的使用的博客哦~
同樣的,數組也有自己的地址,用來存放數組的地址的指針,就是數組指針啦~
int main(){ //定義了一個整型數組 int arr[10] = { 0 }; //定義了一個整數數組的指針 int(*p)[10]; //給整型數組的指針賦值 p = &arr; return 0;}
栗子如下:
int *arr[10];//數組的每個元素是int*
那要把函數的地址存到一個數組中,那這個數組就叫函數指針數組,那函數指針的數組如何定義呢?
int (*parr1[10])();int *parr2[10]();int (*)() parr3[10];
大家覺得哪個才是正確的指針數組的創(chuàng)建呢?
答案是:parr1
parr1 先和 [] 結合,說明parr1是數組,數組的內容是什么呢?
是 int (*)() 類型的函數指針。
今天的內容到這里就要結束啦!
由于今天的內容難度比較大,而且本人的水平有限,難免會有出錯的地方,如果有錯的地方,還請小伙伴們再評論區(qū)提出哦~
讓我們一起學習,一起進步吧!
創(chuàng)作不易呀,希望小伙伴們可以動動小手,給我一個關注、一個贊還有評論哦~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/122194.html
摘要:當集合為空時,稱該二叉樹為空二叉樹。也就是說,如果一個二叉樹的層數為,且結點總數是,則它就是滿二叉樹。完全二叉樹完全二叉樹是效率很高的數據結構,完全二叉樹是由滿二叉樹而引出來的。 ...
閱讀 3582·2021-10-11 10:59
閱讀 1598·2021-09-29 09:35
閱讀 2267·2021-09-26 09:46
閱讀 3780·2021-09-10 10:50
閱讀 958·2019-08-29 12:17
閱讀 827·2019-08-26 13:40
閱讀 2442·2019-08-26 11:44
閱讀 2111·2019-08-26 11:22