找回密码
 用户注册

QQ登录

只需一步,快速开始

查看: 3998|回复: 0

C/C++函数指针总结之二:C函数指针的使用

[复制链接]
发表于 2012-1-17 10:07:33 | 显示全部楼层 |阅读模式
上一篇总结了函数指针的定义、赋值等基本知识。那么函数指针用在哪儿呢?如果象上一篇的例子里面那样用,纯粹就是脱裤子放p,直接使用函数好了。函数指针最经典的应用就是回调了,就是将一个函数1指针作为参数传给另外一个函数2,在这个函数2中就可以用传入的函数指针来调用那个函数。
我们先看看qsort和bsearch吧。假设我从数据库的某个千万以上级别表里面取了几10万条记录需要做运算,现在想根据某(几)个字段排个序,由于这些字段没有索引,若直接用数据库的order by可能会死的很惨,那就用qsort,多方便啊,写个排序函数就行了。#include <stdlib.h>
  1. #include <stdio.h>
  2. #include <string.h>
  3. /*记录结构*/
  4. typedef struct {
  5.     long long id;
  6.     time_t creation_time;
  7.     char code[3];
  8. } TableStruct;
复制代码
针对这个结构定义一个排序函数:
/*排序函数,按term_time降序,code升序 */
  1. int cmp(const void*p1, const void *p2){
  2.     const TableStruct *q1 = (const TableStruct *)p1;
  3.     const TableStruct *q2 = (const TableStruct *)p2;
  4.     if(q1->creation_time < q2->creation_time)
  5.         return 1;
  6.     else if(q1->creation_time > q2->creation_time)
  7.         return -1;
  8.     else
  9.         return strcmp(q1->code, q2->code);
  10. }
复制代码
写个模拟的数据加载函数:int LoadSomeData(TableStruct **ppData){
  1.         int i, n = 10;
  2.         *ppData = (TableStruct*) malloc(sizeof(TableStruct)*n);
  3.         for(i=0; i<10; i++){
  4.                 ((*ppData)+i)->id = i+1;
  5.                 ((*ppData)+i)->creation_time= 1234567890+i%5;
  6.                 sprintf(((*ppData)+i)->code, "A%d", i%10);
  7.         }
  8.         return n;
  9. }
复制代码
主测试程序:int main() {
  1.     /*存放数据的指针*/
  2.     TableStruct *pData = NULL;
  3.     /*从数据库加载相关记录,返回值为加载的记录数*/
  4.     int n = LoadSomeData(&pData);
  5.     if(n<=0){
  6.             return 0;
  7.     }
  8.     else{
  9.         /*gcc里面的函数原型:
  10.         void qsort(void *base, size_t nmemb, size_t size, int(*compar)(const void *, const void *));
  11.         第一个参数是待排序的数据首地址,
  12.         第二个参数是待排序的数据中有多少个元素
  13.         第三个参数是每个元素的大小
  14.         第四个参数就是比较函数的指针 */
  15.         qsort((void*)pData, n, sizeof(TableStruct), cmp); //or &cmp
  16.     }
  17.     int i;
  18.         for(i=0; i<n; i++){
  19.                 printf("id=%lld\n", (pData+i)->id);
  20.                 printf("creation_time=%ld\n", (pData+i)->creation_time);
  21.                 printf("code=%s\n", (pData+i)->code);
  22.         }
  23.         TableStruct criterion; /*只需要填充需要比较的字段*/
  24.         criterion.creation_time = 1234567890;
  25.         strcpy(criterion.code,"A5");
  26.         TableStruct* pResult = (TableStruct*) bsearch((const void*)&criterion, (const void*)pData, n, sizeof(TableStruct), cmp);
  27.         if(pResult == NULL){
  28.                 printf("Not found");
  29.         }
  30.         else{  /*found*/
  31.                 printf("id = %lld\n", pResult->id);
  32.         }
  33.     free(pData);
  34.     return 0;
  35. }
复制代码

在我目前使用的c-tree数据库的C/C++API里面,提供了一些事件的处理机制。这个处理机制也是通过回调函数的方式来实现的。你只要给某个事件登记一个你自定义的函数(当然需要符合要求,就跟qsort的排序函数需要返回大于0,小于0和等于0一样)的指针,那么在数据库发生该事件的时候就会自动调用你的函数。这相当于在C/C++这一层提供了SQL里面的触发器功能。例如CTDB_ON_RECORD_AFTER_WRITE这个事件,就可以在某个表写入记录时做一些事情。
//定义回调函数CTDBRET ctdbDECL onRecordAfterWrite(CTHANDLE Handle){…}//在相关地方注册回调函数if (ctdbSetCallback(hRecord, CTDB_ON_RECORD_AFTER_WRITE, OnRecordAfterWrite) != CTDBRET_OK)    printf("ctdbSetCallback failed\n");
在某些硬件提供的API里面也经常会用回调函数。只要调用其提供的相关接口函数注册自定义的回调函数,在硬件内部发生某个事件时(如报告某类数据),相应的回调函数就会被调用。在回调函数内,你就可以得到硬件内部返回出来的消息和数据。

作者:mosaic 发表于2012-1-16 20:38:28 原文链接

您需要登录后才可以回帖 登录 | 用户注册

本版积分规则

Archiver|手机版|小黑屋|ACE Developer ( 京ICP备06055248号 )

GMT+8, 2024-12-22 17:55 , Processed in 0.014522 second(s), 5 queries , Redis On.

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表