[英]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
您只传递一个指向函数的指针,而不是调用函数本身。 对numeric
或strcmp
的调用发生在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.