C中函数指针最重要的两个用途:
(1)作为另一个函数的参数
(2)转换表(jump table)
C语言中,()的优先级大于*,因此函数int *f()与int (*f)(),前者返回值为int型的指针,后者f为指向函数的指针。
编写一个简单的链表测试用例,测试函数指针作为另一个函数的参数的用途。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
typedef struct node{
void *data;
struct node *next;
}Node;
typedef struct list{
Node *head;
Node *tail;
int list_len;
}List;
typedef struct test{
char *dest_addr;
char *local_addr;
int link_quality;
}Test;
int compare_str(const void *s1, const void *s2)
{
Test *a, *b;
a = (Test *)s1;
b = (Test *)s2;
if (!memcmp(a, b, sizeof(Test))){
return 0;
}
return 1;
}
void handle(void * data)
{
Test *n;
n = (Test *)data;
printf("dest_addr: %s\n", n->dest_addr);
printf("local_addr: %s\n", n->local_addr);
printf("link_quality: %d\n\n", n->link_quality);
}
void list_init(List *list)
{
list->head = NULL;
list->tail = NULL;
list->list_len = 0;
}
void list_destroy(List *list, void(*destroy)(void *))
{
list->list_len = 0;
Node *n, *tmp;
n = list->head;
while (n){
tmp = n->next;
if (destroy){
destroy(n->data);
}
free(n);
n = tmp;
}
}
void list_traverse(List *list, void(*handle)(void *))
{
Node *p;
p = list->head;
while (p){
handle(p->data);
p = p->next;
}
}
Node* make_node(void *data)
{
Node *n;
n = malloc(sizeof(struct node));
assert(n != NULL);
n->next = NULL;
n->data = data;
return n;
}
void list_insert(List *list, void *data)
{
Node *n;
n = make_node(data);
if (list->head == NULL){
list->head = n;
list->tail = n;
n->next = NULL;
}
else{
list->tail->next = n;
list->tail = n;
n->next = NULL;
}
list->list_len++;
}
void* list_search(List *list, void *key, int(*compare)(const void *, const void *))
{
int i = 1;
Node *n;
n = list->head;
while (n){
if (!compare(n->data, key)){
printf("List Node Number: %d\n", i);
return n->data;
}
n = n->next;
i++;
}
return NULL;
}
void main()
{
Node *n;
List *list;
list = (List *)malloc(sizeof(List));
list_init(list);
Test n1 = { "192.168.5.10", "192.168.5.12", 1};
Test n2 = { "192.168.5.20", "192.168.5.22", 2 };
Test n3 = { "192.168.5.30", "192.168.5.32", 3 };
Test nt = { "192.168.5.20", "192.168.5.22", 2 };
list_insert(list, &n1);
list_insert(list, &n2);
list_insert(list, &n3);
printf("list_length: %d\n", list->list_len);
list_traverse(list, handle);
n = list_search(list, &nt, compare_str);
if (n != NULL){
printf("Find List Node \n");
}
list_destroy(list, 0);
system("pause");
}
使用到的函数指针有两个:void (*handle)(void *)和int (*compare)(const void *, const void *)
分别用于遍历时的数据处理以及结点数据比较。
第二种转移表的用途主要用于取代switch,定义int (*func[])(int, int)。其意义为元素函数指针的数组。