2

what is the magic on the finding function below?

1) what is this inner mechanism that allows match to be used without being declared previously?

2) In main , shouldn't the finding call pass the array ADS along with sports_no_trucks?

Thanks in advance!

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

int NUM_ADS = 2;
char *ADS[] = {
    "Luis: SLM ND likes sports, theater, art",
    "Mike: DWM DS likes trucks, sports"
};

void finding(int (*match) (char *))
{
    int i;
    puts("Search results:");
    puts("------------------------------------");
    for (i = 0; i < NUM_ADS; i++)
    {
        if (match(ADS[i]))
        {
            printf("%s\n", ADS[i]);
        }
    }
    puts("------------------------------------");
}

int sports_no_trucks(char *s)
{
    return strstr(s, "sports") && !strstr(s, "trucks");
}


int main()
{

    finding(sports_no_trucks);
    return 0;
}
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
guilherme
  • 25
  • 3
  • 2
    Close "dupe" of [this](https://stackoverflow.com/questions/840501/how-do-function-pointers-in-c-work). `match` is a pointer to a function. It's declared in the parameter list. – Carcigenicate Jun 07 '20 at 00:17
  • match is a function parameter parameter. The function prototype declares it. – 0___________ Jun 07 '20 at 00:49

3 Answers3

0

int name(char *s) declares name to be a function taking a char *s argument and returning an int.

int (*name)(char *s) declares name to be a pointer to a function of that type.

In void finding(int (*match) (char *)), we see the parameter match declared as described above.

1) what is this inner mechanism that allows match to be used without being declared previously?

match is declared before it is used; in void finding(int (*match) (char *)), it is declared to be a parameter to the function finding, with the type described above.

2) In main , shouldn't the finding call pass the array ADS along with sports_no_trucks?

It does not have to because ADS is declared outside any function and before finding is defined, so ADS is visible to the code inside finding. (Using external identifiers like this is generally considered bad design if it can be avoided.)

Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
0

In this function declaration

void finding(int (*match) (char *));

there is declared one parameter with the name match that has the type of pointer to function of the type int( char * ). That is the parameter match itself has the type int ( * )( char * ).

In the call of the function finding

finding(sports_no_trucks);

there is passed as an argument function designator sports_no_trucks that corresponds to the following definition of the function

int sports_no_trucks(char *s)
{
    return strstr(s, "sports") && !strstr(s, "trucks");
}

So the parameter match of the function finding gets the value of the pointer to the function sports_no_trucks because function designators used in expressions are converted to pointers to functions.

You can imagine the definition of the function finding and its call the following way

finding(sports_no_trucks);

//...

void finding( /* int (*match) (char *) */ )
{
    int ( *match )( char * ) = sports_no_trucks;
    //...
}

To make it more clear you can introduce a typedef name like

typedef int FN( char * );

In this case the declaration of the function finding will look like

void finding( FN *match );

where FN is an alias for the function type int( char * ).

2) In main , shouldn't the finding call pass the array ADS along with sports_no_trucks?

The array declared as a global variable

int NUM_ADS = 2;
char *ADS[] = {
    "Luis: SLM ND likes sports, theater, art",
    "Mike: DWM DS likes trucks, sports"
};

And the function finding has access to it because it is visible in the file scope of the program

for (i = 0; i < NUM_ADS; i++)
{
    if (match(ADS[i]))
    {
        printf("%s\n", ADS[i]);
    }
}

But you are right. It is a bad style of programming when functions depend on global variables. In this case you are unable to call the function for another array. So this function is not a general function. It is very specific and can deal with only one array.

There was no need to declare the array as global and define the function that depends on the global array.

In this case the function declaration can look like

void finding( char * s[], size_t n, int (*match) (char *));

and the function could be called for the array ADS like

finding( ADS, NUM_ADS, sports_no_trucks );

But it could be called for any other array the same way

finding( AnotherArray, ItsSize, sports_no_trucks );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
0

Maybe it will be easier to understand in this form

typedef int functype(char *);

void finding(functype *func)
{
    /* ... */    
}

functype is type of function returning int and taking parameter of char *

functype *func is a pointer to this type. And now it looks as any other pointer

ADS is a global variable which can accessed everywhere in the program.

0___________
  • 60,014
  • 4
  • 34
  • 74