Dan*_*ana 7 c kernighan-and-ritchie
可能重复:
编译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));
Run Code Online (Sandbox Code Playgroud)
该程序在没有segfaulting的情况下执行,但我喜欢尽可能地发出警告,或者至少了解它们的原因.
numcmp的函数声明如下:
int numcmp(char *, char *);
Run Code Online (Sandbox Code Playgroud)
但根据联机帮助页,stcmp有这个签名:
int strcmp(const char *s1, const char *s2);
Run Code Online (Sandbox Code Playgroud)
由于方法签名略有不同,警告是否简单?忽视警告会有什么后果?
虽然您可以隐式地将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));
Run Code Online (Sandbox Code Playgroud)
qsort的现代签名是
void
qsort(void *base, size_t nel, size_t width,
int (*compar)(const void *, const void *));
Run Code Online (Sandbox Code Playgroud)
问题const似乎没有在您的问题中发挥作用,但K&R没有const.
尝试诊断它的一种方法是看看如果将表达式替换为 ?: 并仅使用两者之一会发生什么。
如果它只发生在 strcmp 而不是 numcmp,那么很可能是因为 const char*。我认为虽然 char* 总是可以转换为 void*,但您不能“安全”地将 const char* 转换为 void*。
如果两者都存在,那么这可能是关于函数指针的一些问题,其中将 char* 转换为 void* 可以工作,但签名应该相同,并且使用 void 而不是 char 是一个问题。