C語言函數指針的用法

函數指針是一種在C、C++、D語言、其他類 C 語言和Fortran 2003中的指針。函數指針可以像一般函數一樣,用於調用函數、傳遞參數。在如 C 這樣的語言中,通過提供一個簡單的選取、執行函數的方法,函數指針可以簡化代碼。

函數指針只能指向具有特定特徵的函數。因而所有被同一指針運用的函數必須具有相同的參數和返回類型。

下面的代碼說明了一種初始化函數指針的方法:

int f(int);
int (*fp)(int) = &f;

//使用三種方式調用函數
int ans;
ans = f(25);
ans = (*pf)(25);
ans = pf(25);
 以下爲函數指針在C中的簡單運用:
#include <stdio.h>

int max(int x, int y)
{
    return x > y ? x : y;
}
 
int main(void)
{
    /* p 是函數指針 */
    int (* p)(int, int) = & max; // &可以省略
    int a, b, c, d;
 
    printf("please input 3 numbers:");
    scanf("%d %d %d", & a, & b, & c);
 
    /* 與直接調用函數等價,d = max(max(a, b), c) */
    d = (* p)(( *p)(a, b), c); 
 
    printf("the maxumum number is: %d\n", d);
    return 0;
}
 下面介紹函數指針最常見的兩個用途:作爲參數傳遞給另一個函數(回調函數)、轉換表
1、回調函數:

下面有一個簡單的函數,用來在單鏈表中查找一個給定的值

Node* search_list(Node* node, int const value)
{
    while(node != NULL) {
        if(node->value == value)
            break;
        node = node->next;
    }
    return node;
}

 一種更加通用的方法就是使該函數能用任何類型值的鏈表,必須修改函數,使它與類型無關。解決的方案就是使用函數指針。

#include <stdio.h>
#include "node.h"

Node *search_list( Node *node, void const *value,
    int (*compare)( void const *, void const * ) )
{
    while( node != NULL ){
        if( compare( &node->value, value ) == 0 )
            break;
        node = node->next;
    }
    return node;
}

 在特定的鏈表中進行比較的時候,用戶需要編寫適當的比較函數,並把指向該函數的指針和指向需要查找的值的指針傳遞給查找函數,下面是一個整型鏈表中查找的比較函數:

int compare_ints(void const *a, void const *b)
{
    if( *(int *)a == *(int *)b)
        return 0;
    else
        return 1;
}

//這個函數將像下面這樣調用
desired_node = search_list(root, &desired_value, compare_ints);
 如果你希望在一個字符串鏈表中進行查找,下面的代碼可以完成任務:
#include<string.h>
...
desired_node = search_list(root, "desired_value", strcmp);
 再看一個完整的例子:
#include<stdio.h>
struct object
{
    int data;
};
 
int object_compare(struct object * a,struct object * z)
{
    return a->data < z->data ? 1 : 0;
}
 
struct object *maximum(struct object * begin,struct object * end,int (* compare)(struct object *, struct object *))
{
    struct object * result = begin;
    while(begin != end)
    {
        if(compare(result, begin))
        {
            result = begin;
        }
        ++ begin;
    }
    return result;
}
 
int main(void)
{
    struct object data[8] = {{0}, {1}, {2}, {3}, {4}, {5}, {6}, {7}};
    struct object * max;
    max = maximum(data + 0, data + 8, & object_compare);
    printf("max: %d\n", (*max).data);
    return 0;
}
 2、轉移表

下面的程序是一個簡化的根據運算符轉到相應運算的例子:

#include<stdio.h>

double _add(double, double);
double _sub(double, double);
double _mul(double, double);
double _div(double, double);

double _add(double a, double b)
{
    return a + b;
}

double _sub(double a, double b)
{
    return a - b;
}

double _mul(double a, double b)
{
    return a * b;
}

double _div(double a, double b)
{
    return a / b;
}

int main(void)
{
    int n;
    enum Operation{ADD, SUB, MUL, DIV}op;
    double a, b, ans;
    a = 0.232332;
    b = 0.234398;
    printf("請輸入一個整數(0-3): ");
    scanf("%d", &n);
    op = (enum Operation)n;
    switch(op) {
    case ADD:
        ans = _add(a, b);
        break;
    case SUB:
        ans = _sub(a, b);
        break;
    case MUL:
        ans = _mul(a, b);
        break;
    case DIV:
        ans = _div(a, b);
        break;
    default:
        break;
    }
    printf("%lf\n", ans);
    return 0;
}
 使用可以使用轉換表來實現相同的任務,轉換表就是一個函數指針數組,代碼如下:
#include<stdio.h>
double _add(double, double);
double _sub(double, double);
double _mul(double, double);
double _div(double, double);

double _add(double a, double b)
{
    return a + b;
}

double _sub(double a, double b)
{
    return a - b;
}

double _mul(double a, double b)
{
    return a * b;
}

double _div(double a, double b)
{
    return a / b;
}

int main(void)
{
    int n;    double a, b, ans;
    a = 0.232332;
    b = 0.234398;
    printf("請輸入一個整數(0-3): ");
    scanf("%d", &n);

    double (*oper_func[])(double, double) = {
        _add, _sub, _mul, _div
    };

    ans = oper_func[n](a, b);
    printf("%lf\n", ans);
    return 0;
}

 

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章