Unable to understand pointers to functions in C
我正在阅读K&R的"C编程语言",无法理解函数指针的概念。为了解释指向函数的指针,它给出了一个程序作为示例,如果给定了可选参数-n,那么程序将按数字而不是按字典顺序对输入行排序。程序如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | #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 "); return 1; } } |
我的问题是:
1)在调用qsort时,为什么没有传递void*类型的参数(在粗体和斜体部分)?
2)在调用qsort(粗体和斜体部分)时,(*)单独做什么,它正在取消引用的函数在哪里?
有人能澄清我的疑虑吗?
当调用
为了更好地解释它,让我们制作一个小示例程序,演示如何使用和调用函数指针:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <stdio.h> void hello(const char *name) { printf("Hello %s ", 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 } |
如您所见,向函数传递指针与向
如果你有,例如
1 | get_name_and_greet(hello("foo")); |
号
您可以调用
至于
关于回答你的问题1。和2.我认为你可以从阅读螺旋法则中获益:
http://c-faq.com/decl/spiral.anderson.html.
它有助于将看似复杂的C语句(如函数指针)转换为简单的英语:
1 |
"qsort"是一个接受四个参数的函数,返回void
参数0—
参数1—
参数2-
参数3—
然后在你呼叫"qsort"时:
。
您提供了这些必要的参数,更具体地说,让我们来看第三个参数:
1 |
最后一个括号的计算结果为"numcmp"或"stcmp"。在这两种情况下,都是返回int的函数,唯一的区别是传入参数的数据类型。在不失去一般性的情况下,让我们选择"numcmp"。
那么我们有:
1 | (int (*)(void*,void*))(numcmp) |
。
我们在"numcmp"的左边有一个cast,它处理函数"numcmp"和"strcmp"参数的数据类型的差异。在K&R2中,它实际上解释了这一点:
"函数参数的详细转换将转换比较函数的参数。这些通常对实际表示没有影响,但要确保编译器一切正常。"
此外,"stcmp"和"numcmp"是函数的地址,因为它们是函数,所以不需要&;运算符。