无法理解C中函数的指针

时间:2018-02-06 08:25:20

标签: c pointers function-pointers

我正在阅读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的调用中(在粗体和斜体部分中),那是什么(*)单独执行,它取消引用的函数在哪里?

有人可以澄清我的怀疑。

2 个答案:

答案 0 :(得分:2)

当您致电qsort时,您只将指针传递给函数,您不会调用该函数本身。对numericstrcmp的调用发生在qsort函数内(您不应自行声明,而是包含<stdlib.h>,如this qsort reference所示,如果&qsort #39; s您正在呼叫的标准#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*))没有返回任何内容,并且会导致编译错误。

至于:host /deep/ :not(.mat-focused) .mat-input-placeholder.mat-empty { color: transparent; } :host /deep/ :not(.mat-focused) .mat-input-placeholder.mat-empty::before { content: "My custom placeholder"; color: black; } 部分,它是一个简单的类型转换。

答案 1 :(得分:1)

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

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

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

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

&#39;的qsort&#39;是一个带有四个参数的函数,返回void

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

参数1 - left - 一个int。

参数2 - right - 一个int。

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

然后在打电话给&#39; qsort&#39;:

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

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

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

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

那么我们就有了:

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

我们在&#39; numcmp&#39;的左侧有什么?然后是一个演员,它负责处理函数&#39; numcmp&#39;之间的参数的数据类型的差异。和&#39; strcmp&#39;。在K&amp; R2中,它实际上解释了这一点:

&#34;函数参数的精细演员强制转换了比较函数的参数。这些通常对实际表示没有影响,但保证编译器一切正常。&#34;

此外,&#39; stcmp&#39;和&#39; numcmp&#39;是函数的地址,并且由于它们已知是函数,因此它们是函数。不需要操作员。