我最近在C语言中有一些函数指针的经验。

因此,按照回答自己问题的传统,我决定对最基本的问题做一个简短的总结,以供那些需要快速切入主题的人使用。


当前回答

我最喜欢的函数指针用途之一是迭代器-

#include <stdio.h>
#define MAX_COLORS  256

typedef struct {
    char* name;
    int red;
    int green;
    int blue;
} Color;

Color Colors[MAX_COLORS];


void eachColor (void (*fp)(Color *c)) {
    int i;
    for (i=0; i<MAX_COLORS; i++)
        (*fp)(&Colors[i]);
}

void printColor(Color* c) {
    if (c->name)
        printf("%s = %i,%i,%i\n", c->name, c->red, c->green, c->blue);
}

int main() {
    Colors[0].name="red";
    Colors[0].red=255;
    Colors[1].name="blue";
    Colors[1].blue=255;
    Colors[2].name="black";

    eachColor(printColor);
}

其他回答

由于函数指针通常是类型化回调,因此您可能需要查看类型安全回调。这同样适用于非回调函数的入口点等。

C相当善变,同时也很宽容:)

“从头开始”功能具有“开始执行的内存地址”。在汇编语言中,它们被称为(调用“函数的内存地址”)。现在回到C。如果函数有内存地址,那么它们可以由C中的指针操作

1.首先需要声明一个指向函数的指针2.传递所需函数的地址

****注意->函数应为相同类型****

这个简单的计划将说明一切。

#include<stdio.h>
void (*print)() ;//Declare a  Function Pointers
void sayhello();//Declare The Function Whose Address is to be passed
                //The Functions should Be of Same Type
int main()
{
 print=sayhello;//Addressof sayhello is assigned to print
 print();//print Does A call To The Function 
 return 0;
}

void sayhello()
{
 printf("\n Hello World");
}

之后,让我们来看看机器是如何理解它们的。32位体系结构的上述程序的机器指令一瞥。

红色标记区域显示地址如何在eax中交换和存储。然后是eax上的调用指令。eax包含函数所需的地址。

C中的函数指针

让我们从一个我们将要指向的基本函数开始:

int addInt(int n, int m) {
    return n+m;
}

首先,让我们定义一个指向接收2个int并返回一个int的函数的指针:

int (*functionPtr)(int,int);

现在我们可以安全地指出我们的功能:

functionPtr = &addInt;

现在我们有一个指向函数的指针,让我们使用它:

int sum = (*functionPtr)(2, 3); // sum == 5

将指针传递给另一个函数基本上是相同的:

int add2to3(int (*functionPtr)(int, int)) {
    return (*functionPtr)(2, 3);
}

我们也可以在返回值中使用函数指针(尽量跟上,这会变得很混乱):

// this is a function called functionFactory which receives parameter n
// and returns a pointer to another function which receives two ints
// and it returns another int
int (*functionFactory(int n))(int, int) {
    printf("Got parameter %d", n);
    int (*functionPtr)(int,int) = &addInt;
    return functionPtr;
}

但使用typedef要好得多:

typedef int (*myFuncDef)(int, int);
// note that the typedef name is indeed myFuncDef

myFuncDef functionFactory(int n) {
    printf("Got parameter %d", n);
    myFuncDef functionPtr = &addInt;
    return functionPtr;
}

指向函数的指针很有用,因为正如《C编程语言》一书所说,C中的函数不是变量。这意味着,

// Say you have add function
int add(int x, int y){
    return x + y;
}

// Say you have another add function
int another_add(int x, int y){
    return y + x;
}


int main(){
    // Although the types of another_add and add are same
    // You can't do
    another_add = add
    
    // You have a compute function that takes a function of int's signature
    int (*compute)(int, int);
   
    // You won't even be able to pass functions to other functions
    // (Although when you do, C is just passing the pointer to that function)
    // So, compute(add) is really compute(&add)
    // But you can create a pointer to functions that are variables
    // you can assign to and/or pass to other functions

    int (*operation)(int, int);
    // Now you can do
    operation = &add;
    // You could also do, the following to do the same thing
    // When a function is passed in right hand side of assignment,
    // C knows that you mean pointer, and you don't need explicit &
    operation = add;
}

同样,数组也不是C中的变量。您可以编写一个与上面类似的示例并进行测试。

我最喜欢的函数指针用途之一是迭代器-

#include <stdio.h>
#define MAX_COLORS  256

typedef struct {
    char* name;
    int red;
    int green;
    int blue;
} Color;

Color Colors[MAX_COLORS];


void eachColor (void (*fp)(Color *c)) {
    int i;
    for (i=0; i<MAX_COLORS; i++)
        (*fp)(&Colors[i]);
}

void printColor(Color* c) {
    if (c->name)
        printf("%s = %i,%i,%i\n", c->name, c->red, c->green, c->blue);
}

int main() {
    Colors[0].name="red";
    Colors[0].red=255;
    Colors[1].name="blue";
    Colors[1].blue=255;
    Colors[2].name="black";

    eachColor(printColor);
}