溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點(diǎn)擊 登錄注冊 即表示同意《億速云用戶服務(wù)條款》

【C語言】函數(shù)指針與回調(diào)函數(shù)

發(fā)布時間:2020-06-27 11:09:32 來源:網(wǎng)絡(luò) 閱讀:832 作者:q381989042 欄目:編程語言

在C語言中:指針是C語言的特色,有著各種各樣的指針,普通的變量指針,常量指針,數(shù)組指針,指針數(shù)組,函數(shù)指針,指針函數(shù)。我們就講一下函數(shù)指針與回調(diào)函數(shù)吧


首先關(guān)于函數(shù)指針,其實(shí)很簡單。

    對于一個函數(shù)指針來說,顧名思義,就是一個指向函數(shù)的指針,需要知道的是,對于指針而言,他總是存儲一塊地址,地址里面有著一個,一組,或者一塊數(shù)據(jù),在函數(shù)中,函數(shù)的存儲是放在代碼段的,每個函數(shù)都有著一個函數(shù)首地址,調(diào)用了這個地址相當(dāng)于調(diào)用的這個函數(shù)。

    具體的可以觀看我的這篇博客,其中就通過在內(nèi)存階段改變棧幀返回值,成功的調(diào)用了一個重啟函數(shù)。淺談棧幀(一)

    其實(shí)C++特性中的虛函數(shù)表就有利用這一點(diǎn)。

    所以說呢,函數(shù)指針就是一個指向函數(shù)首地址的指針,好了,先了解這個定義,然后我們進(jìn)入下一個階段。

    

對于指針,他不僅僅要指向一個具體的量,他還需要其他的標(biāo)識符來描述這個量的具體屬性。

  例如:char* str,void *func(int,int);

在指針符號*的左右,都是在描述這個指針的具體信息。

那么對于函數(shù)指針而言,這是怎么樣的呢。

    void (*f) ( );雖然()的優(yōu)先級高于*,但由于有括號存在,首先執(zhí)行的是解引用,所以f是一個指針;接下來執(zhí)行( ),表明f指向一個函數(shù),這個函數(shù)不返回任何值?,F(xiàn)在得出結(jié)論:f是一個指向不接受參數(shù)且不返回任何值的函數(shù)的指針,簡稱函數(shù)指針(pointer to function)。

<1>.初始化

注意指向函數(shù)的指針(函數(shù)指針)指向的是函數(shù)而非普通的變量,它所指向的函數(shù)也是有特定類型的,函數(shù)的類型由它的返回值類型以及形參列表確定,和函數(shù)名無關(guān)。對函數(shù)指針初始化時可以采用相同類型函數(shù)的函數(shù)名或函數(shù)指針(當(dāng)然還有零指針常量)。假如有函數(shù)void test ( ),int wrong_match (int)和函數(shù)指針void (*ptf) ( )。

下面的初始化是錯誤的,因?yàn)楹瘮?shù)指針的類型與函數(shù)的類型不匹配:

f = wrong_match;

f = & wrong_match;

ptf = wrong_match;

ptf = & wrong_match;

以下初始化及賦值是合法的:

f = test;

f = &test;

ptf = test;

ptf = &test;

f = pf;

要做出解釋的是test&test都可以用來初始化函數(shù)指針。C語言規(guī)定函數(shù)名會被轉(zhuǎn)換為指向這個函數(shù)的指針,除非這個函數(shù)名作為操作符或sizeof操作符的操作數(shù)(注意:函數(shù)名用于sizeof的操作數(shù)是非法的)。也就是說f = test;test被自動轉(zhuǎn)換為&test,而f= &test;中已經(jīng)顯示使用了&test,所以test就不會再發(fā)生轉(zhuǎn)換了。因此直接引用函數(shù)名等效于在函數(shù)名上應(yīng)用 & 運(yùn)算符,兩種方法都會得到指向該函數(shù)的指針。


int (*function(int)) (double*,char);要了解此聲明的含義,首先來看function(int),將function聲明為一個函數(shù),它帶有一個int型的形式參數(shù),這個函數(shù)的返回值為一個指針,正是我們本將開頭講過的函數(shù)指針int (*) (double*, char);這個指針指向一個函數(shù),此函數(shù)返回int型并帶有兩個分別是double*型和char型的形參。如果使用typedef可以將這個聲明簡化:

typedef int (*ptf) (double*, char);

ptf function(int );

總結(jié):

    其實(shí)對于函數(shù)指針來說。我們只需要記住。從最中間括號開始往外逐步分析,函數(shù)指針是(*)

而指針函數(shù)是(*()),懂得會分區(qū),就知道函數(shù)指針是什么東西了。弄清楚他本身名字,然后弄清楚他的描述情況。


回調(diào)函數(shù):

    上面已經(jīng)說清楚了對于函數(shù)指針而言,他有著他自己的名字,有著相對于的描述信息,信息不一樣的無法進(jìn)行賦值配對,然后既然有函數(shù)指針這種東西?那么他出現(xiàn)是干什么用的呢?

    其實(shí)對于函數(shù)指針,無非就是讓我們在面臨不同情況去使用他。函數(shù)指針指向不同的情況,來進(jìn)行不同的操作,在主題函數(shù)處理中提供不同的函數(shù)指針借口,借此來處理不同的情況。

    計(jì)算機(jī)程序設(shè)計(jì)中,回調(diào)函數(shù),或簡稱回調(diào)(Callback 即call then back 被主函數(shù)調(diào)用運(yùn)算后會返回主函數(shù)),是指通過函數(shù)參數(shù)傳遞到其它代碼的,某一塊可執(zhí)行代碼引用。這一設(shè)計(jì)允許了底層代碼調(diào)用在高層定義的子程序。

    來看一個簡單例子:

#include <stdio.h>

int int_cmp(const void * p1, const void * p2)
{
    if (*( int *)p1 > *(int *) p2)
    {
        return 1;
    }
    else if (*( int *)p1 == *(int *) p2)
    {
        return 0;
    }
    else
    {
        return -1;
    }
}

void _swap(void *p1, void * p2, int size)
{
    int i = 0;
    for (i = 0; i< size; i++)
    {
        char tmp = *((char *)p1 + i);
       *(( char *)p1 + i) = *((char *) p2 + i);
       *(( char *)p2 + i) = tmp;
    }
}
void bubble(void *base, int count , int size, int(*cmp )(void *, void *))
{
    int i = 0;
    int j = 0;
    for (i = 0; i< count - 1; i++)
    {
        for (j = 0; j<count - i - 1; j++)
       {
            if (cmp ((char *) base + j*size , (char *)base + (j + 1)*size) > 0)
           {
               _swap(( char *)base + j*size, (char *)base + (j + 1)*size, size);
           }
       }
    }
}
int main()
{
    int arr[] = { 1, 3, 5, 7, 9, 2, 4, 6, 8, 0 };
    //char *arr[] = {"aaaa","dddd","cccc","bbbb"};
    int i = 0;
    bubble(arr, sizeof(arr) / sizeof(arr[0]), sizeof (int), int_cmp);
    for (i = 0; i< sizeof(arr) / sizeof(arr[0]); i++)
    {
       printf( "%d ", arr[i]);
    }
    printf("\n");
    return 0;
}



向AI問一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI