1. 基本概念
首先,应该明确:
- 程序运行期间,每个函数都会占用一段连续的内存空间。
- 函数名就是该函数所占内存区域的起始地址(也 称“入口地址”)
- 将函数的入口地址赋给一个指针变量,使该指 针变量指向该函数。然后通过指针变量就可以 调用这个函数。这种指向函数的指针变量称为 “函数指针”。
函数指针定义的一般形式为:
类型名 (* 指针变量名)(参数类型1, 参数类型2,…);
“类型名”表示被指函数的返回值的类型。
“(参数类型1, 参数类型2,……)”中则依次列出了被指函数的所有参数的类型。例如:
int (*pf)(int ,char);
表示pf是一个函数指针,它所指向的函数,返回值 类型应是int,该函数应有两个参数,第一个是int 类 型,第二个是char类型。
- 可以用一个原型匹配的函数的名字给一个函数指针赋值。
- 要通过函数指针调用它所指向的函数,写法为:
函数指针名(实参表);
下面的程序说明了函数指针的用法:
#include <stdio.h>
void PrintMin(int a, int b){
if( a<b ) printf("%d",a);
else
printf("%d",b);
}
int main(){
void (* pf)(int ,int);
int x = 4, y = 5;
pf = PrintMin;
pf(x,y);
return 0;
}
输出结果为:4
2. 函数指针应用:快速排序库函数qsort
看看qsort函数的定义:
void qsort(void *base, int nelem,
unsigned int width,
int ( * pfCompare)(const void *, const void *));
- base是待排序数组的起始地址;
- nelem是待排序数组的元素个数;
- width是待排序数组的每个元素的大小(以字节单位;
- 最后一个参数 pfCompare是一个函数指针,它指向一个“比较函 数”。
排序就是一个不断比较并交换位置的过程。 qsort如何在连元素的类型是什么都不知道的情 况下,比较两个元素并判断哪个应该在前呢?
答案是,qsort函数在执行期间,会通过 pfCompare指针调用一个 “比较函数”,用以判断两个元素哪个更应该排在前面。
这个“比较函数”不是C/C++的库函数,而是由使用 qsort的程序员编写的。
在调用qsort时,将“比较函数”的名字作为实参传递给 pfCompare。程序员当然清楚该按什么规则决定哪个元素应该在前,哪个元素应该在后,这个规则就体 现在“比较函数”中。
qsort函数的用法规定,“比较函数”的原型应是:
int 函数名(const void * elem1, const void * elem2);
该函数的两个参数,elem1和elem2,指向待比 较的两个元素。也就是说, * elem1和 * elem2 就是待比较的两个元素。该函数必须具有以下
行为:
- 如果 * elem1应该排在 * elem2前面,则函数返回值是 负整数(任何负整数都行)。
- 如果 * elem1和* elem2哪个排在前面都行,那么函数 返回0
- 如果 * elem1应该排在 * elem2后面,则函数返回值是 正整数(任何正整数都行)
一个栗子:
下面的程序,功能是调用qsort库函数,将一个 unsigned int数组按照个位数从小到大进行排 序。比如 8,23,15三个数,按个位数从小到 大排序,就应该是 23,15,8。
#include <stdio.h>
#include <stdlib.h>
int MyCompare(const void * elem1, const void * elem2 ){
unsigned int * p1, * p2;
p1 = (unsigned int *) elem1;
p2 = (unsigned int *) elem2; return (*p1%10) -(*p2%10);
}
#define NUM 5
int main(){
unsigned int an[NUM] = { 8,123,11,10,4 };
qsort(an, NUM, sizeof(unsigned int),MyCompare);
for(int i = 0;i < NUM; i ++ )
printf("%d ", an[i]); return 0;
输出结果:
10 11 123 4 8