来自K&R C的示例中的指针类型不匹配警告

可能重复:
问题编译K&R示例

最近,我一直在通过K&R的C编程语言。

在5.11节中,它们涵盖了函数的指针,并在输入他们的示例之后 – 一个quicksort实现,我们提供了一个指向我们想要使用的比较函数的指针 – 我从编译器收到警告:条件表达式中的指针类型不匹配。 (我的编译器是OS X 10.5.6上的gcc 4.0.1)

触发警告的示例中的行是:

qsort((void **) lineptr, 0, nlines-1, (int (*)(void*, void*))(numeric ? numcmp : strcmp)); 

程序执行没有segfaulting,但我喜欢每个警告,或至少了解他们的原因。

numcmp的函数声明如下:

  int numcmp(char *, char *); 

但是根据联机帮助页,stcmp有这个签名:

  int strcmp(const char *s1, const char *s2); 

由于方法签名略有不同,警告是否简单? 忽视警告会有什么后果?

虽然您可以隐式地将char *强制转换为void *,但对于具有这些类型的函数指针(不带警告),您不能执行相同的操作。 编译器对函数签名的类型匹配更加小心。

更不用说在qsort中发生的事情恰恰相反:也就是说,void *将被转换为numcmp中的char *和strcmp中的const char *。

编译器应该在这些情况下发出警告。 如果你真的必须使用一个与参数类型不同的函数,也许你应该使用一个匹配类型的包装函数,然后在调用原始函数时进行适当的显式转换。

例如:

 static int strcmp_wrapper(void* s1, void* s2) { return strcmp((char*)s1, (char*)s2); } static int numcmp_wrapper(void* n1, void* n2) { return numcmp((char*)n1, (char*)n2); } qsort((void **) lineptr, 0, nlines-1, (numeric ? numcmp_wrapper : strcmp_wrapper)); 

qsort的现代签名是

 void qsort(void *base, size_t nel, size_t width, int (*compar)(const void *, const void *)); 

const的问题似乎没有在你的问题中发挥作用,但K&R没有const

简答:K&R不知道C.

答案很长:当他们开始时没有人知道C时,他们受到了限制,所以他们在进行的时候就是这样做的。

(略微)长篇答案中不那么轻浮的forms:自从K&R写完以来,语言已经发展了(有些人会说已经改变了 ),但除非你通过动态示例变形获得电子书版本,否则你的副本中的例子K&R将不会跟上“新的和批准的”(“现在有更多ANSI!”)语言。

尝试和诊断它的一种方法是看看如果将表达式替换为?:只有两个中的一个,会发生什么。

如果它只发生在strcmp而不是numcmp,那么它很可能是因为const char *。 我认为虽然char *总是可以转换为void *,但是你不能将const char *转换为void *作为“安全”。

如果它同时存在,则可能这是关于函数指针的一些问题,其中将char *转换为void *工作,但签名应该相同并且具有空隙而不是字符是一个问题。