【问题标题】:C Pointers - Function pointer passed as a paramterC 指针 - 作为参数传递的函数指针
【发布时间】:2016-10-25 23:53:30
【问题描述】:

问题空间:

我在理解以下最终参数的语法时遇到了一点麻烦,它是作为参数传递的函数指针:

    qsort(
        (void **) lineptr, 0, nlines - 1,

        /* Can't understand the following syntax */
        (int (*)(void*, void*))(numberic ? numcmp : strcmp)
    );

我确实理解了另一种方法:

    int (*fn)(void*, void*);
    if(numeric) {
        fn = numcmp;
    } else {
        fn = strcmp;
    }

它们都产生编译器错误:warning: assignment from incompatible pointer type

代码:

#include <stdio.h>
#include <string.h>
#include "alloc.h"
#include "line.h"
#include "qsort.h"
#include "numcmp.h"

char *lineptr[MAXLINES];

int main(int argc, char *argv[])
{
    int nlines; /* number of input lines read */
    int numeric = 0;

    if (argc > 1 && strcmp(argv[1], "-n") == 0)
        numeric = 1;

    if((nlines = readlines(lineptr, MAXLINES)) >= 0) {

        /* 
            qsort with custome soring function passed as a parameter
            throught pointers
        */
        int (*fn)(void*, void*);
        if(numeric) {
            fn = numcmp;
        } else {
            fn = strcmp;
        }

        qsort((void **) lineptr, 0, nlines - 1, fn);

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

        printf("Sorted and tailed:\n");
        writelines(lineptr, nlines);

        return 0;
    } else {
        printf("error: input to big to sort\n");
        return 1;
    }
}

【问题讨论】:

  • 警告有什么不清楚的地方? (我假设你已经阅读了qsort 的手册并且知道它的参数。)
  • 没什么只是想指出,以防其他人会代替。我想我只需要更改指针类型以匹配函数。
  • @KerrekSB 是的,我做了man qsort,他们似乎都是(const void *, const void *)
  • (int (*)(void*, void*))whateverwhatever 到相应类型的转换(指向返回 int 并采用两个 void * 参数的函数的指针)。
  • 提示:如果代码是干净的,则不需要强制转换。

标签: c pointers function-pointers


【解决方案1】:

它本质上是从三元表达式的结果到函数指针的转换,该函数指针应该是qsort中的相应参数。因此,按照(a)b 的思路,b 是三元表达式,a 是函数指针声明。

int (*)(void*, void*) 声明一个指向函数的指针,该函数接受两个 void * 参数并返回一个 int

注意(*)

  • 如果删除括号,您将获得一个返回指向 int 的指针的函数。
  • 使用括号,您有一个指向返回 int 的函数的指针。

找出不同之处。


有一个很棒的实用程序cdecl 可以解释这样的声明。这是适合您的情况:

cdecl> explain (int (*)(void*, void*))
cast unknown_name into pointer to function (pointer to void, pointer to  void) returning int

(遗憾的是,使用三元表达式时它似乎失败了:`bad character ':'。你必须弥补那部分。)

通过cdecl.org在线试用,或在本地安装。

(关于解密 C 声明 was on Hacker News recently 的相关讨论,其中提到了 clockwise/spiral rule 的替代方案。)

【讨论】:

  • 我明白了,最后一个愚蠢的问题,所以整个语句只是对函数 (int (*)(void*, void*))(numberic ? numcmp : strcmp) 的强制转换,所以它在某种意义上相当于:int d = 1; float f = (float)d?
  • 这是,在一个非常模糊的意义上:只是在他们都是演员的意义上。另外,您的编译器警告告诉我们,在实际情况下,强制转换可能不是真正有效的,您只能希望最好(但要为分段错误和数据丢失等做好准备)。
  • 是的,这正是我的意思。将int 转换为float 似乎很简单,但是将带有两个参数的未知函数指针转换为函数似乎有点复杂,至少在我习惯之前是这样。
  • “似乎有点复杂,至少在我习惯之前”。如果您对此感到厌烦,请转到指向函数的指针,该函数将函数指针数组作为参数,并返回一个双精度数组(指针)。如果您想知道一个用例:用于数值工作的通用(多维)优化例程可能会显示此类内容(尽管将数组作为参数而不是作为返回值更好,并且结构和 typedef 有助于此处的可读性)。跨度>
  • 呃,我明白了。是的,我看到我们可以有函数指针数组并将其传递给另一个函数,那时我的想法开始有点飘,我就像嗯,如果我创建一个指向 exit() 的函数指针并递归地将它传递给 @987654339 @,会发生什么我不知道哈哈,好吧,最后一个显然是个笑话。 =)
猜你喜欢
  • 2021-10-05
  • 1970-01-01
  • 2012-11-28
  • 2020-11-08
  • 2012-01-24
  • 2012-07-22
  • 2022-01-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多