зачем передавать в качестве аргумента функции функцию? - PullRequest
0 голосов
/ 10 июля 2019

У меня есть маленький вопрос.я изучаю C с devc ++ (как начало), и я видел в качестве функции аргумента, вы можете передать функцию, это нормально, но почему?например, вы можете написать в качестве аргумента:

void myfunc(void(*func)(int)){}

, но если вы просто вызываете функцию со своим именем и аргументом, это не лучше?

как пример:

void myfunction (){name of func to call(myargs);  }

есть разница?кажется, то же самое, но с более простым и коротким кодом

edit:

я хочу знать только

void map (int (*fun) (int),int x[ ], int l) {
    for(i = 0; i < l; i++)
    x[i] = fun(x[i]);
}

почему вы используете это вместо:

void map (int x[ ], int l) {
    for(i = 0; i < l; i++)
    x[i] = nameoffunction(yourargument);
}

Ответы [ 3 ]

1 голос
/ 10 июля 2019

Очень хороший пример - классическая функция сортировки qsort. Это библиотечная функция, которая означает, что у вас есть доступ только к ее прототипу. Чтобы сделать qsort общим, вам нужно написать собственную функцию сравнения. Типичная реализация выглядит так для обычных целых чисел:

int cmpfunc (const void * a, const void * b)
{
   return ( *(int*)a - *(int*)b ); 
}

И затем, если у вас есть массив arr целых чисел, вы можете отсортировать его с помощью qsort(arr, sizeof(arr), cmpfunc)

Вы можете спросить, почему это не встроено в функцию qsort? В конце концов, было бы легко заставить это работать и для чисел с плавающей точкой и для целых чисел. Да, но представьте, если у вас есть массив структур, которые выглядят так:

struct {
    char *firstname;
    char *lastname;
    int age;
} persons[10];

Как бы вы отсортировали это? Ну, это не очевидно. Вы можете хотеть все три. В этом случае напишите три разные функции сравнения.

1 голос
/ 10 июля 2019

Вы можете использовать указатель функции в качестве параметра, если хотите, чтобы ваша функция выполняла разные действия в зависимости от того, что хочет пользователь.

Вот простой пример:

#include <stdio.h>

int add(int x, int y)
{
    return x + y;
}

int subtract(int x, int y)
{
    return x - y;
}

int multiply(int x, int y)
{
    return x * y;
}

int divide(int x, int y)
{
    return x / y;
}

int operation(int x, int y, int (*func)(int, int))
{
    printf("  x=%d, y=%d\n", x, y);
    return func(x,y);
}

int main()
{
    int x = 8, y = 4;

    printf("x+y=%d\n", operation(x,y,add));
    printf("x-y=%d\n", operation(x,y,subtract));
    printf("x*y=%d\n", operation(x,y,multiply));
    printf("x/y=%d\n", operation(x,y,divide));
    return 0;
 }
0 голосов
/ 11 июля 2019
я хочу только знать
void map (int (*fun) (int),int x[ ], int l) {
    for(i = 0; i < l; i++)
    x[i] = fun(x[i]);
}
почему вы используете это вместо:
void map (int x[ ], int l) {
    for(i = 0; i < l; i++)
    x[i] = nameoffunction(yourargument);
}

Давайте ответим на вопрос вопросом - что, если вы хотите выполнить более одного типа картирования? Что, если вы хотите отобразить и x 2 и & radic; x ?

Конечно, вы могли бы сделать что-то вроде

void map( int x[], int l, int type )
{
  for ( int i = 0; i < l; i++ )
  {
    if ( type == MAP_SQUARED )
      x[i] = int_square( x );
    else if ( type == MAP_ROOT )
      x[i] = int_root( x );
    ...
  }
}

, который работает, но трудно читать и громоздок в обслуживании - каждый раз, когда вы хотите выполнить новое отображение, вы должны добавить новый случай в функцию map.

Сравните это с

void map( int x[], int l, int (*fun)(int) )
{
  for ( int i = 0; i < l; i++ )
    x[i] = fun( x[i] );
}
...
map( x, l, int_square );
map( y, l, int_root );

Вам не нужно взламывать функцию map, чтобы получить различные сопоставления - вам нужно только передать функцию, которая работает с отдельными элементами. Если вы хотите выполнить новое отображение, все, что вам нужно сделать, это написать новую функцию - вам совсем не нужно редактировать функцию map.

Стандартная библиотека C использует эту форму делегирования в нескольких местах, включая функцию qsort (позволяющую сортировать массивы любого типа в любом порядке) и функцию signal (позволяющую изменять реакцию программы прерывать динамически).

...