关于 C 中的函数指针

About function pointers in C

下面的 finding 函数有什么神奇之处?

1) 允许使用 match 而无需事先声明的内部机制是什么?

2) 在 main 中, finding 调用不应该将数组 ADSsports_no_trucks 一起传递吗?

提前致谢!

#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;
}

int name(char *s)name 声明为一个接受 char *s 参数并返回 int.

的函数

int (*name)(char *s)name 声明为指向该类型函数的指针。

void finding(int (*match) (char *))中,我们看到参数match声明如上。

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

match 在使用前声明;在 void finding(int (*match) (char *)) 中,它被声明为函数 finding 的参数,具有上述类型。

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

不必如此,因为 ADS 是在任何函数外部声明的,并且在定义 finding 之前,所以 ADSfinding 内部的代码可见。 (如果可以避免的话,像这样使用外部标识符通常被认为是糟糕的设计。)

在此函数声明中

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

声明了一个名称为 match 的参数,其类型为指向函数的指针类型 int( char * )。那就是参数 match 本身的类型是 int ( * )( char * ).

在函数的调用中finding

finding(sports_no_trucks);

作为参数传递的函数指示符 sports_no_trucks 对应于函数的以下定义

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

所以函数finding的参数match得到函数指针的值sports_no_trucks因为表达式中使用的函数指示符被转换为函数指针

你可以想象函数finding的定义及其调用方式

finding(sports_no_trucks);

//...

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

为了更清楚,您可以引入一个 typedef 名称,例如

typedef int FN( char * );

在这种情况下,函数查找的声明将如下所示

void finding( FN *match );

其中 FN 是函数类型 int( char * ).

的别名

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

声明为全局变量的数组

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

并且函数 finding 可以访问它,因为它在程序的文件范围内可见

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

但你是对的。当函数依赖于全局变量时,这是一种糟糕的编程风格。在这种情况下,您无法为另一个数组调用该函数。所以这个函数不是一般的函数。它非常具体,只能处理一个数组。

无需将数组声明为全局数组并定义依赖于全局数组的函数。

在这种情况下,函数声明可以如下所示

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

并且可以为数组 ADS 调用该函数,例如

finding( ADS, NUM_ADS, sports_no_trucks );

但是可以用同样的方式为任何其他数组调用它

finding( AnotherArray, ItsSize, sports_no_trucks );

也许这样写会更容易理解

typedef int functype(char *);

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

functype 是返回 int 并采用 char *

参数的函数类型

functype *func 是指向该类型的指针。现在它看起来和任何其他指针一样

ADS是一个全局变量,可以在程序的任何地方访问。