[英]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.