前言
指針是用來在程序中指向某一個(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)行了排序