混淆K&;R5.11函数指针C

混淆K&;R5.11函数指针C,c,pointers,casting,function-pointers,kernighan-and-ritchie,C,Pointers,Casting,Function Pointers,Kernighan And Ritchie,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)); } 我理解三元运算符,但假设numeric=

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));
}
我理解三元运算符,但假设numeric==0,这是什么意思

(int (*)(void *, void*))strcmp;
函数参数的数据类型是否不匹配

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

我可以使用强制转换在代码中键入函数指针吗?

  (int (*)(void *, void*))strcmp;
表示,
strcmp()
是一个函数指针,它接受两个
void*
参数并返回一个
int

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

[…]如果已转换 指针用于调用类型与引用类型不兼容的函数, 该行为未定义


但是,在您的例子中,对于参数类型,
char*
void*
彼此别名,因此类型转换类型与实际有效类型兼容,因此(稍后)定义了函数调用。

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

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


我想提醒您,今天的标准库的
qsort
具有与K&R示例不同的函数签名(和语义)。今天的
qsort
获取指向元素向量开头的指针,并使用指向数组中元素的指针调用compare函数;对于字符串指针数组,参数是指向不适用于
strcmp()
的指针的指针。必须首先取消对参数的引用。有一个strcmp
wrapper的例子,它就是这样做的。(手册页web导出看起来有些混乱,但仍然可读。)

所以我所做的是将int-strcmp(char*,char*)键入int-strcmp(void*,void*),并将其作为参数传递?在这种情况下,强制转换也是不必要的,不是吗?简单调用
qsort
,最后一个参数为
strcmp
,应该可以工作,因为从
const char*
void*
@R\u Kapp的隐式转换是正确的,但所有隐式转换可能都无效,对不对?@Pruzo否,根据Sourav引用的文本,函数指针转换是未定义的行为。摆脱它的唯一方法是通过
qsort
将函数定义更改为期望的格式,或者用正确的格式将这些函数包装到其他函数中。@Pruzo例如:
int wrap_strcmp(const void*o1,const void*o2){return strcmp(o1,o2)}
小心K&R,这是一本危险的书,它教授了许多不正确或糟糕的编程实践。示例5.11就是这样一个示例,因为代码依赖于未定义的行为。此外,正如我们所看到的,K&R代码也是一个无法阅读的烂摊子。我总是因为在某个地方发布类似K&R的代码而被激怒,谢谢你!你的问题很好,问题出在K&R书上,而不是你的问题。询问这些事情是非常合理的,因为假设语言的创造者比其他任何人都更了解语言似乎是合乎逻辑的。唉,直到1989年才是这样。试图将K&R手册升级到据称符合ISO C标准的第二版是草率的;还有很多标准前的代码。@Lundin,这似乎表明你很迂腐;-)在我看来,K&R是世界上最好的技术书籍之一。事实上,它的可用性和可读性以及在保持乐趣的同时的务实态度是C如此成功的原因之一。将其与Algol68上的报告进行比较。。。此后,C标准得到了改进,因为在一些边缘情况或异国建筑中,某些结构可能会崩溃,但这肯定不是其中之一。