什么是函数指针,我将如何使用它们?

时间:2021-11-02 20:56:06

I understand I can use pointers for functions.

我知道我可以使用指针来实现功能。

Can someone explain why one would use them, and how? Short example code would be very helpful to me.

有人可以解释为什么会使用它们,以及如何使用它们?简短的示例代码对我很有帮助。

9 个解决方案

#1


22  

A simple case is like this: You have an array of operations (functions) according to your business logic. You have a hashing function that reduces an input problem to one of the business logic functions. A clean code would have an array of function pointers, and your program will deduce an index to that array from the input and call it.

一个简单的例子是这样的:根据您的业务逻辑,您有一系列操作(函数)。您有一个散列函数可以将输入问题减少到其中一个业务逻辑函数。一个干净的代码将有一个函数指针数组,您的程序将从输入推断出该数组的索引并调用它。

Here is a sample code:

这是一个示例代码:

typedef void (*fn)(void) FNTYPE;
FNTYPE fn_arr[5];

fn_arr[0] = fun1; // fun1 is previously defined
fn_arr[1] = fun2;
...

void callMyFun(string inp) {
    int idx = decideWhichFun(inp); // returns an int between 0 and 4
    fn_arr[idx]();
}

But of course, callbacks are the most common usage. Sample code below:

但当然,回调是最常见的用法。示例代码如下:

void doLengthyOperation(string inp, void (*callback)(string status)) {
  // do the lengthy task
  callback("finished");
}

void fnAfterLengthyTask(string status) {
    cout << status << endl;
}

int main() {
    doLengthyOperation(someinput, fnAfterLengthyTask);
}

#2


13  

One quite common use case is a callback function. For example if you load something from a DB you can implement your loading function so that it reports the progress to a callback function. This can be done with function pointers.

一个非常常见的用例是回调函数。例如,如果从DB加载某些内容,则可以实现加载功能,以便将进度报告给回调函数。这可以通过函数指针完成。

#3


5  

Callbacks. I make an asynchronous call to a chunk of code and want it to let me know when it finishes, I can send it a function pointer to call once it's done.

回调。我对一大块代码进行异步调用,并希望它在完成时让我知道,我可以向它发送一个函数指针,一旦完成就调用它。

#4


3  

I'm surprised no one mentioned "state machines". Function pointers are a very common way to implement state machines for tasks such as parsing. See for example: link.

我很惊讶没有人提到“国家机器”。函数指针是为解析等任务实现状态机的一种非常常见的方法。参见例如:链接。

#5


3  

You use a function pointer when you need to give a callback method. One of the classic example is to register signal handlers - which function will be called when your program gets SIGTERM (Ctrl-C)

您需要提供回调方法时使用函数指针。一个典型的例子是注册信号处理程序 - 当程序获得SIGTERM(Ctrl-C)时将调用该函数

Here is another example:

这是另一个例子:

// The four arithmetic operations ... one of these functions is selected
// at runtime with a switch or a function pointer
float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }

// Solution with a switch-statement - <opCode> specifies which operation to execute
void Switch(float a, float b, char opCode)
{
   float result;

   // execute operation
   switch(opCode)
   {
      case '+' : result = Plus     (a, b); break;
      case '-' : result = Minus    (a, b); break;
      case '*' : result = Multiply (a, b); break;
      case '/' : result = Divide   (a, b); break;
   }

   cout << "Switch: 2+5=" << result << endl;         // display result
}  

// Solution with a function pointer - <pt2Func> is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// "specifies" which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
   float result = pt2Func(a, b);    // call using function pointer

   cout << "Switch replaced by function pointer: 2-5=";  // display result
   cout << result << endl;
}

You can learn more about function pointers here http://www.newty.de/fpt/index.html

您可以在http://www.newty.de/fpt/index.html上了解有关函数指针的更多信息

If you are more familiar with object-oriented languages, you can think of it as C's way to implement the strategy design pattern.

如果您对面向对象语言更熟悉,可以将其视为C实现策略设计模式的方法。

#6


1  

Let's do a map-like function for C.

让我们为C做类似地图的功能。

void apply(int *arr, size_t len, int (*func)(int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(arr[i]);
}

That way, we can transform a function that works on integers to work on arrays of integers. We could also do a similar version:

这样,我们可以转换一个对整数有效的函数来处理整数数组。我们也可以做类似的版本:

void apply_enumerated(int *arr, size_t len, int (*func)(size_t, int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(i, arr[i]);
}

This does the same thing, but allows our function to know which element it's on. We could use this, for example:

这也是一样的,但允许我们的函数知道它所在的元素。我们可以使用它,例如:

int cube(int i) { return i * i * i }

void print_array(int *array, size_t len, char *sep)
{
    if(sep == NULL) sep = ", ";
    printf("%d", *array);
    for(size_t i = 1; i < len; i++) printf("%s%d", sep, array[i])
}

#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply(array, ARRAY_SIZE(array), cube);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

That code will print:

该代码将打印:

1, 2, 3, 4, 5
1, 8, 27, 64, 125

For our enumeration example:

对于我们的枚举示例:

int mult(size_t i, int j) { return i * j }

// print_array and ARRAY_SIZE as before

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply_enumerated(array, ARRAY_SIZE(array), mult);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

This prints:

这打印:

1, 2, 3, 4, 5
0, 2, 6, 12, 20

As a more real world example, a string library could have a function that applies a function that operates on single characters to all the characters in the string. An example of such functions are the standard-library toupper() and tolower() functions in ctype.h - we could use this string_apply() function to make a string_toupper() function easily.

作为一个更真实的例子,字符串库可以具有一个函数,该函数将对单个字符进行操作的函数应用于字符串中的所有字符。这种函数的一个例子是ctype.h中的标准库toupper()和tolower()函数 - 我们可以使用这个string_apply()函数轻松地创建一个string_toupper()函数。

#7


1  

A very good and easy to understand tutorial: http://www.newty.de/fpt/index.html

一个非常好且易于理解的教程:http://www.newty.de/fpt/index.html

Hope this helps.

希望这可以帮助。

#8


0  

Another usage for pointers is iterating lists or arrays.

指针的另一个用法是迭代列表或数组。

#9


0  

For code, check out qrdl's response to state machines tutorials.

对于代码,请查看qrdl对状态机教程的响应。

I've used a variant of his method to implement a a menu for an LCD display I have on a board. Very very useful, makes the coding much cleaner and easier to read. Using function pointers makes expanding the number, names and ordering of menus very easy, and hides all those details from the higher level calling function that just sees 'hey, I write to the LCD here.'

我已经使用他的方法的变体来实现我在板上的LCD显示器的菜单。非常有用,使编码更清晰,更易于阅读。使用函数指针可以非常轻松地扩展菜单的数量,名称和顺序,并隐藏所有那些细节,这些函数只是看到了“嘿,我在这里写入LCD”。

#1


22  

A simple case is like this: You have an array of operations (functions) according to your business logic. You have a hashing function that reduces an input problem to one of the business logic functions. A clean code would have an array of function pointers, and your program will deduce an index to that array from the input and call it.

一个简单的例子是这样的:根据您的业务逻辑,您有一系列操作(函数)。您有一个散列函数可以将输入问题减少到其中一个业务逻辑函数。一个干净的代码将有一个函数指针数组,您的程序将从输入推断出该数组的索引并调用它。

Here is a sample code:

这是一个示例代码:

typedef void (*fn)(void) FNTYPE;
FNTYPE fn_arr[5];

fn_arr[0] = fun1; // fun1 is previously defined
fn_arr[1] = fun2;
...

void callMyFun(string inp) {
    int idx = decideWhichFun(inp); // returns an int between 0 and 4
    fn_arr[idx]();
}

But of course, callbacks are the most common usage. Sample code below:

但当然,回调是最常见的用法。示例代码如下:

void doLengthyOperation(string inp, void (*callback)(string status)) {
  // do the lengthy task
  callback("finished");
}

void fnAfterLengthyTask(string status) {
    cout << status << endl;
}

int main() {
    doLengthyOperation(someinput, fnAfterLengthyTask);
}

#2


13  

One quite common use case is a callback function. For example if you load something from a DB you can implement your loading function so that it reports the progress to a callback function. This can be done with function pointers.

一个非常常见的用例是回调函数。例如,如果从DB加载某些内容,则可以实现加载功能,以便将进度报告给回调函数。这可以通过函数指针完成。

#3


5  

Callbacks. I make an asynchronous call to a chunk of code and want it to let me know when it finishes, I can send it a function pointer to call once it's done.

回调。我对一大块代码进行异步调用,并希望它在完成时让我知道,我可以向它发送一个函数指针,一旦完成就调用它。

#4


3  

I'm surprised no one mentioned "state machines". Function pointers are a very common way to implement state machines for tasks such as parsing. See for example: link.

我很惊讶没有人提到“国家机器”。函数指针是为解析等任务实现状态机的一种非常常见的方法。参见例如:链接。

#5


3  

You use a function pointer when you need to give a callback method. One of the classic example is to register signal handlers - which function will be called when your program gets SIGTERM (Ctrl-C)

您需要提供回调方法时使用函数指针。一个典型的例子是注册信号处理程序 - 当程序获得SIGTERM(Ctrl-C)时将调用该函数

Here is another example:

这是另一个例子:

// The four arithmetic operations ... one of these functions is selected
// at runtime with a switch or a function pointer
float Plus    (float a, float b) { return a+b; }
float Minus   (float a, float b) { return a-b; }
float Multiply(float a, float b) { return a*b; }
float Divide  (float a, float b) { return a/b; }

// Solution with a switch-statement - <opCode> specifies which operation to execute
void Switch(float a, float b, char opCode)
{
   float result;

   // execute operation
   switch(opCode)
   {
      case '+' : result = Plus     (a, b); break;
      case '-' : result = Minus    (a, b); break;
      case '*' : result = Multiply (a, b); break;
      case '/' : result = Divide   (a, b); break;
   }

   cout << "Switch: 2+5=" << result << endl;         // display result
}  

// Solution with a function pointer - <pt2Func> is a function pointer and points to
// a function which takes two floats and returns a float. The function pointer
// "specifies" which operation shall be executed.
void Switch_With_Function_Pointer(float a, float b, float (*pt2Func)(float, float))
{
   float result = pt2Func(a, b);    // call using function pointer

   cout << "Switch replaced by function pointer: 2-5=";  // display result
   cout << result << endl;
}

You can learn more about function pointers here http://www.newty.de/fpt/index.html

您可以在http://www.newty.de/fpt/index.html上了解有关函数指针的更多信息

If you are more familiar with object-oriented languages, you can think of it as C's way to implement the strategy design pattern.

如果您对面向对象语言更熟悉,可以将其视为C实现策略设计模式的方法。

#6


1  

Let's do a map-like function for C.

让我们为C做类似地图的功能。

void apply(int *arr, size_t len, int (*func)(int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(arr[i]);
}

That way, we can transform a function that works on integers to work on arrays of integers. We could also do a similar version:

这样,我们可以转换一个对整数有效的函数来处理整数数组。我们也可以做类似的版本:

void apply_enumerated(int *arr, size_t len, int (*func)(size_t, int))
{
    for(size_t i = 0; i < len; i++)
        arr[i] = func(i, arr[i]);
}

This does the same thing, but allows our function to know which element it's on. We could use this, for example:

这也是一样的,但允许我们的函数知道它所在的元素。我们可以使用它,例如:

int cube(int i) { return i * i * i }

void print_array(int *array, size_t len, char *sep)
{
    if(sep == NULL) sep = ", ";
    printf("%d", *array);
    for(size_t i = 1; i < len; i++) printf("%s%d", sep, array[i])
}

#define ARRAY_SIZE(a) (sizeof(a)/sizeof((a)[0]))

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply(array, ARRAY_SIZE(array), cube);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

That code will print:

该代码将打印:

1, 2, 3, 4, 5
1, 8, 27, 64, 125

For our enumeration example:

对于我们的枚举示例:

int mult(size_t i, int j) { return i * j }

// print_array and ARRAY_SIZE as before

int main(void)
{
    int array[5] = { 1, 2, 3, 4, 5 };
    print_array(array, ARRAY_SIZE(array), NULL);
    apply_enumerated(array, ARRAY_SIZE(array), mult);
    print_array(array, ARRAY_SIZE(array), NULL);
    return 0;
}

This prints:

这打印:

1, 2, 3, 4, 5
0, 2, 6, 12, 20

As a more real world example, a string library could have a function that applies a function that operates on single characters to all the characters in the string. An example of such functions are the standard-library toupper() and tolower() functions in ctype.h - we could use this string_apply() function to make a string_toupper() function easily.

作为一个更真实的例子,字符串库可以具有一个函数,该函数将对单个字符进行操作的函数应用于字符串中的所有字符。这种函数的一个例子是ctype.h中的标准库toupper()和tolower()函数 - 我们可以使用这个string_apply()函数轻松地创建一个string_toupper()函数。

#7


1  

A very good and easy to understand tutorial: http://www.newty.de/fpt/index.html

一个非常好且易于理解的教程:http://www.newty.de/fpt/index.html

Hope this helps.

希望这可以帮助。

#8


0  

Another usage for pointers is iterating lists or arrays.

指针的另一个用法是迭代列表或数组。

#9


0  

For code, check out qrdl's response to state machines tutorials.

对于代码,请查看qrdl对状态机教程的响应。

I've used a variant of his method to implement a a menu for an LCD display I have on a board. Very very useful, makes the coding much cleaner and easier to read. Using function pointers makes expanding the number, names and ordering of menus very easy, and hides all those details from the higher level calling function that just sees 'hey, I write to the LCD here.'

我已经使用他的方法的变体来实现我在板上的LCD显示器的菜单。非常有用,使编码更清晰,更易于阅读。使用函数指针可以非常轻松地扩展菜单的数量,名称和顺序,并隐藏所有那些细节,这些函数只是看到了“嘿,我在这里写入LCD”。