指针(六)

今天继续对指针进行探讨,请看下面:

函数指针:
 
下面通过一个程序,简单明了的对函数指针有个基本认识:
#include <stdio.h>

void test(int n)
{
    printf("test %d ...\n", n);
}

int main(void)
{
    void (*f)(int);    // 这里的f就是函数指针变量
    void (*f2)(int);    // 这里的f就是函数指针变量
    // 以下两种写法是等价的
    f = &test;
    f2 = test;

    // 以下两种写法也是等价的
    f(100);    // 调用函数
    (*f2)(200);        // 调用函数

    return 0;
}

运行:

需要特别说明的是:

void (*f)(int);代表的是函数指针变量,但是
void* f(int);则代表的含义就完全不一样了,由于()运算符的优先级比*要高,所以f(int)代表一个函数,void*代表函数的返回值。
 
下面再通过几个小例子,来进一步加深对函数指针的认识:
示例1:
 
运行结果:
如果不用函数指针,也不可能用一个函数可以包含多个函数的功能,从代码复用的角度来说,用它也是非常好的体现。
 
示例2【它有一个很重要的意义,需好好理解】:
这个示例主要是用到系统函数,对结构体数组元素进行排序,这个函数为qsort,通过man帮助查看一下:
 
具体代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

typedef struct month
{
    int number;
    char* name;
} month_t;

//第一种排序规则是以名字升序进行排序
int comp1(const void* m1, const void* m2)
{
    month_t* mi1 = (month_t*)m1;
    month_t* mi2 = (month_t*)m2;
    return strcmp(mi1->name, mi2->name);
}

//第二种排序规则是以数字降序进行排序
int comp2(const void* m1, const void* m2)
{
    month_t* mi1 = (month_t*)m1;
    month_t* mi2 = (month_t*)m2;
    return mi2->number - mi1->number;
}

//输出结构体的元素内容
void output(month_t* months, int number)
{
    int i;
    for (i=0; i<number; i++)
    {
        printf("%d %s\n", months[i].number, months[i].name);
    }
}

int main(void)
{
    month_t months[] = {
        { 1, "jan" }, { 2, "feb" }, { 3, "mar" }, { 4, "apr" },
        { 5, "may" }, { 6, "jun" }, { 7, "jul" }, { 8, "aug" },
        { 9, "sep" }, {10, "oct" }, {11, "nov" }, {12, "dec" }
    };

    //算出结构体的个数
    int number_of_months = sizeof(months) / sizeof(month_t);
    qsort(months, number_of_months, sizeof(month_t), comp1);//排序规则跟java中的排序一样,类似于方法回调
    output(months, number_of_months);

    putchar('\n');
    qsort(months, number_of_months, sizeof(month_t), comp2);
    output(months, number_of_months);

    return 0;
}

运行:

分析:
 
通过函数指针,可以让我们的代码更加通用,是实现通用编程的一种很重要的手段
 
typedef用法:
typedef为一种类型引入新的名字,类似于宏替换,但是存在差别,请看下面:
下面,以一个实际的函数例子,这些例子在linux系统编程中会大量用到,在此正好理解它们,它就是signal:
 
void (*signal(int signum, void (*handler)(int)))(int);
下面一一剖析来理解上面的这种函数的定义:
 
上面的这种写法,很难理解,这时,就可以用typedef来让程序的可读性增强:
 
typedef void (*sighandler_t)(int);//这时sighandler_t就不是函数指针变量了,而是函数指针类型
 
 
sighandler_t signal(int signum, sighandler_t handler);//这时,signal的第二个参数就可用函数指针类型代替,由于signal的返回值也是个函数指针,这样一来,就明了多了;
 
通过man来查看一下这个系统函数的声明,具体用法先不用知道,后面再学,先看下函数原形声明:
 
 
指针数据类型小结:
下面最后理解一下这个复杂的表达式:
好了,先学到这,今天学的函数指针形态有些难懂,需好好体现,下次见!!
 

posted on 2013-12-17 21:10  cexo  阅读(230)  评论(0编辑  收藏  举报

导航