K&R 5.11 函数指针 C 中的混淆线

Confusing line in K&R 5.11 function pointers C

main()这一行的最后一个参数让我迷路了

// declaration
void qsort(char *linep[], int left, int right, int (*compare)(void *, void*);

// use
main(){
    qsort((void**) lineptr, 0, nlines-1, (int (*)(void*,void*))(numeric ?
    numcmp : strcmp));
}

我理解三元运算符,但让我们说数字 == 0 那么这是什么意思?

(int (*)(void *, void*))strcmp;

函数参数的数据类型是否不匹配?

int strcmp(const char*, const char*);
void qsort( , , , int(*)(void*)(void*);

我可以类型转换函数指针吗?

在您的代码中,使用强制转换

  (int (*)(void *, void*))strcmp;

表示strcmp()是一个函数指针,有两个void *参数和returns一个int.

通常,对于函数指针,转换是一个非常糟糕的主意,正如引用自 C11,第 6.3.2.3 章

[...] If a converted pointer is used to call a function whose type is not compatible with the referenced type, the behavior is undefined.

但是,在您的情况下,对于参数类型,char *void * 互为别名,因此类型转换类型 compatible 与实际有效类型,因此(稍后)定义了函数调用。

是的,您可以将函数指针转换为指向具有不同签名的函数的指针。根据您的调用约定(谁清理堆栈?调用者还是被调用者?)如果参数数量不同或参数大小不同,调用该函数将是错误的。

这里也不是这种情况:在您的标准架构(sun 工作站、Linux PC、raspberry PI)上,指向不同数据类型的参数指针以相同的方式表示,因此不会造成任何损害。该函数将从堆栈中读取 4 或 8 字节的值,并将指向的内存解释为预期类型的​​数据(它应该有,例如,不要在字符串上使用浮点比较函数;它可能会抛出,因为任意位模式可以是 NaN 等)。

我想提醒您,今天的标准库 qsort 与 K&R 的示例具有不同的函数签名(和语义)。今天的qsort得到一个指向元素向量开头的指针,用指向数组中元素的指针调用比较函数;在字符串指针数组的情况下,参数是 指向指针 的指针,不适合 strcmp()。参数必须首先取消引用。 linux man page for qsort 有一个 strcmp 包装器的例子,它就是这样做的。 (手册页 Web 导出看起来有些乱码,但仍然可读。)