繁体   English   中英

无法理解 C 中指向函数的指针

[英]Unable to understand pointers to functions in C

我正在阅读 K&R 的“C 编程语言”,但无法理解函数指针的概念。 为了解释指向函数的指针,它以一个程序为例,如果给出了可选参数 -n,则该程序按数字而不是按字典顺序对输入行进行排序。 这是程序:

  #include <stdio.h>
    #include <string.h>
    #define MAXLINES 5000     /* max #lines to be sorted */
    char *lineptr[MAXLINES];  /* pointers to text lines */
    int readlines(char *lineptr[], int nlines);
    void writelines(char *lineptr[], int nlines);
    void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));
    int numcmp(char *, char *);
    /*sort input lines */
    main(int argc, char *argv[])
    {
      int nlines;  /*number of input lines read */
      int numeric =0;  /* 1 if numeric sort */
      if (argc>1 && strcmp(argv[1], "-n")==0)
      numeric=1;
      if ((nlines= readlines(lineptr, MAXLINES))>=0)
      {
         qsort((void **) lineptr,0,nlines-1, ***(int (*)(void*,void*))(numeric?numcmp:strcmp));***
         writelines(lineptr, nlines);
         return 0;
}
      else
      {
        printf("input too big to sort\n");
        return 1;
       }


}

我的问题是:

1) 在对 qsort 的调用中,为什么没有传递 void* 类型的参数(在粗体和斜体部分)?

2)在对qsort的调用(在粗体和斜体部分)中,那个(*)在做什么,它正在取消引用的函数在哪里?

有人可以澄清我的疑问。

当您调用qsort您只传递一个指向函数的指针,而不是调用函数本身。 numericstrcmp的调用发生在qsort函数内部(您不应该声明自己,而是包括<stdlib.h>如在这个qsort参考中所示,如果它是您正在调用的标准qsort )。

为了更好地解释它,让我们制作一个小示例程序,展示如何使用和调用函数指针:

#include <stdio.h>

void hello(const char *name)
{
    printf("Hello %s\n", name);
}

void get_name_and_greet(void (*hello_function)(const char *))
{
    char name[256];
    printf("Please enter name: ");
    scanf("%255s", name);

    hello_function(name);  // Use the function pointer
}

int main(void)
{
    get_name_and_greet(&hello);  // Pass a pointer to the function
}

如您所见,将指针传递给函数与将指针传递给int变量没有什么不同。

如果你做了例如

get_name_and_greet(hello("foo"));

您将调用hello函数,并使用hello返回的内容作为get_name_and_greet参数。 这当然不起作用,因为hello不返回任何内容,并且会导致编译错误。


至于(int (*)(void*,void*))部分,它是一个简单的类型转换。

至于回答你的问题 1. 和 2. 我认为你可能会从阅读螺旋规则中受益:

http://c-faq.com/decl/spiral.anderson.html

它有助于将看似复杂的 C 语句(如函数指针)翻译成简单的英语:

void qsort(void *lineptr[], int left, int right, int (*comp)(void *, void *));

'qsort' 是一个带四个参数的函数,返回 void

参数 0 - lineptr - 一个空指针数组。

参数 1 - left - 一个整数。

参数 2 - right - 一个整数。

参数 3 - comp - 一个指向函数的指针,该函数带有两个参数,每个参数都是一个 void 指针,并返回一个 int。

然后在您对“qsort”的调用中:

qsort((void **) lineptr,0,nlines-1, (int (*)(void*,void*))(numeric?numcmp:strcmp));

您提供了这些必要的参数,更具体地说,让我们看看第三个参数:

(int (*)(void*,void*))(numeric?numcmp:strcmp)

最后一个括号计算为 'numcmp' 或 'stcmp'。 在任何一种情况下,这都是一个返回 int 的函数,唯一的区别是传入参数的数据类型。不失一般性,让我们选择 'numcmp'。

那么我们有:

(int (*)(void*,void*))(numcmp)

我们在 'numcmp' 的左侧是一个强制转换,它负责处理函数 'numcmp' 和 'strcmp' 之间参数数据类型的差异。 在 K&R2 中,它实际上解释了这一点:

“函数参数的精心转换会转换比较函数的参数。这些通常不会对实际表示产生影响,但可以向编译器保证一切正常。”

此外,'stcmp' 和 'numcmp' 是函数的地址,因为它们是函数,所以 & 运算符不是必需的。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM