1 基本概念
程序运行期间,每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址(也称为“入口地址”)。我们可以将函数的入口地址赋给一个指针变量,使该指针变量指向该函数。然后通过指针变量就可以调用这个函数。这种指向函数的指针变量称为“函数指针”。
2 定义形式
类型名(* 指针变量名)(参数类型1, 参数类型2,...);
实例:
uint8_t (* msg)(uint32_t, uint16_t);
3 函数指针和qsort库函数
C语言快速排序库函数:
void qsort(void *base, int nelem, unsugned int width, int(*pfCompare)(const void, const void *));
可以对任意类型的数组进行排序。
对数组排序,需要知道:
- 数组起始地址;
- 数组元素的个数;
- 每个元素的大小(由此可以算出每个元素的地址)
base 待排序数组的起始地址
nelem 待排序数组的元素个数
width 待排序数组的每个元素的大小(以字节为单位)
pfCompare 比较函数的的地址
pfCompare函数指针,它指向一个“比较函数”。
该比较函数应为以下形式:
int 函数名(const void *elem1, const void *elem2);
比较函数是程序员自己编写的。
排序就是一个不断比较并交换位置的过程。
qsort函数在执行期间,会通过pfCompare指针调用“比较函数”,调用时将要比较的两个元素地址传给“比较函数”,然后根据“比较函数”返回值判断两个元素哪个更应该排在前面。
比较函数编写规则:
- 如果 * elem1应该排在 * elem2前面,则函数返回值是负整数;
- 如果 * elem1和 * elem2哪个排在前面都行,那么函数返回0;
- 如果 * elem1应该排在 * elem2后面,则函数返回值是正整数。
4 示例程序:
#include <stdio.h>
#include <stdlib.h>
int MyCompare(const void *elem1, const void *elem2)
{
unsigned int *p1, *p2;
p1 = (unsigned int*)elem1; // “*elem1”非法
p2 = (unsigned int*)elem2; // “*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
站在巨人的肩上
【1】北京大学信息技术学院《程序设计实习》