C/C++函數(shù)指針

前言

指針是用來在程序中指向某一個(gè)變量的,實(shí)際上指針內(nèi)存放的就是一個(gè)變量的相對內(nèi)存地址(實(shí)際的物理地址還要加上一個(gè)偏移值)。

在程序運(yùn)行期間,每個(gè)函數(shù)都會占用一段連續(xù)的內(nèi)存空間,而函數(shù)名就是該函數(shù)所占內(nèi)存空間的起始地址(入口地址),我們可以將一個(gè)函數(shù)的起始地址賦值給一個(gè)指針,進(jìn)而通過該指針來調(diào)用函數(shù),這就是函數(shù)指針。

函數(shù)指針可以像一般函數(shù)一樣,用于調(diào)用函數(shù)、傳遞參數(shù)。在如 C這樣的語言中,通過提供一個(gè)簡單的選取、執(zhí)行函數(shù)的方法,函數(shù)指針可以簡化代碼。函數(shù)指針只能指向具有特定特征的函數(shù)。因而所有被同一指針運(yùn)用的函數(shù)必須具有相同的參數(shù)和返回類型。

C語言標(biāo)準(zhǔn)規(guī)定,函數(shù)指示符(function designator,即函數(shù)名字)既不是左值,也不是右值。但C++語言標(biāo)準(zhǔn)規(guī)定函數(shù)指示符屬于左值,因此函數(shù)指示符轉(zhuǎn)換為函數(shù)指針的右值屬于左值轉(zhuǎn)換為右值。

除了作為sizeof或取地址&的操作數(shù),函數(shù)指示符在表達(dá)式中自動轉(zhuǎn)換為函數(shù)指針類型右值。因此通過一個(gè)函數(shù)指針調(diào)用所指的函數(shù),不需要在函數(shù)指針前加取值或反引用(*)運(yùn)算符。

定義形式

對于一個(gè)函數(shù)指針,我們采用如下的定義方式:

返回值 (* 指針變量名)(參數(shù)類型1,參數(shù)類型2,······)

例如:

int (* pf)(int,int);

其中,

返回值:函數(shù)返回的數(shù)據(jù)類型

指針變量名:函數(shù)指針變量名

參數(shù)類型:函數(shù)的參數(shù)類型

樣例

#include<stdio.h>

int min(int a, int b) {//返回兩個(gè)數(shù)中的最小值函數(shù)
    return a < b ? a : b;
}

int main(){
    //定義一個(gè)函數(shù)指針pf
    int (*pf)(int, int);
    //讓pf指向min函數(shù)
    pf = min;
    //通過函數(shù)名調(diào)用min函數(shù)
    printf("min=%d\n", min(10, 20));
    //通過函數(shù)指針pf調(diào)用min函數(shù)
    printf("pf=%d\n", pf(10, 20));

    return 0;
}

通過運(yùn)行上面的程序,我們得到了以下結(jié)果

min=10
pf=10

從結(jié)果中我們可以看出兩種調(diào)用方式得到了一樣的結(jié)果。接下來我們進(jìn)而修改一下上面的代碼

#include<stdio.h>

int min(int a, int b) {//返回兩個(gè)數(shù)中的最小值函數(shù)
    return a < b ? a : b;
}

int main(){
    //定義一個(gè)函數(shù)指針pf
    int (*pf)(int, int);
    //讓pf指向min函數(shù)
    pf = min;
    //獲取min函數(shù)的地址
    printf("min=  %p\n", &min);
    //查看函數(shù)指針pf內(nèi)的地址
    printf("pf=   %p\n", pf);

    return 0;
}
}

運(yùn)行上面的代碼,我們得到下面的結(jié)果

min=  001C1221
pf=   001C1221

從結(jié)果我們可以明顯的看出pf函數(shù)中存放的確實(shí)是min的地址。

應(yīng)用實(shí)例

C語言中,有一個(gè)常用的快速排序庫函數(shù),能夠?qū)θ我獾臄?shù)組以任意規(guī)則進(jìn)行排序,其形式如下:

void qsort(void *base, size_t nitems, size_t size, 
int (*compar)(const void *, const void*))

其中,

base為將要排序的數(shù)組的首地址

nitems為由base指向的數(shù)組的元素個(gè)數(shù)

size為該數(shù)組中每個(gè)元素的大小

compar為排序規(guī)則函數(shù),其形式如下:

int 函數(shù)名(const void *elem1,const void *elem2);

該函數(shù)的返回值有三種情況:

1.返回負(fù)整數(shù)*elem1排在*elem2前面

2.返回0*elem1*elem2誰在前面都可以

3.返回正整數(shù)*elem1排在*elem2后面

下面我們來考察一個(gè)實(shí)例

#include <stdio.h>
#include <stdlib.h>

int myCompar(const void* a, const void* b){//排序規(guī)則函數(shù)
    //由于*a和*b是兩個(gè)無類型的地址,
    //在使用之前我們先將其強(qiáng)制類型轉(zhuǎn)換為int*,
    //然后再取其值進(jìn)行比較
    return (*(int*)a - *(int*)b);
}

int main(){
    int values[] = { 23, 6, 100, 2, 25 };

    printf("排序之前的列表:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", values[i]);
    }

    //調(diào)用qsort進(jìn)行排序
    qsort(values, 5, sizeof(int), myCompar);

    printf("\n排序之后的列表:\n");
    for (int i = 0; i < 5; i++) {
        printf("%d ", values[i]);
    }

    return 0;
}

運(yùn)行以上程序,我們得到下面所示結(jié)果:

排序之前的列表:
23 6 100 2 25
排序之后的列表:
2 6 23 25 100

經(jīng)過qsort調(diào)用mycompar函數(shù)后成功升序地將數(shù)組進(jìn)行了排序

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

友情鏈接更多精彩內(nèi)容