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

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)

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

Jar*_*aus 7

虽然您可以隐式地将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.


Uri*_*Uri 1

尝试诊断它的一种方法是看看如果将表达式替换为 ?: 并仅使用两者之一会发生什么。

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

如果两者都存在,那么这可能是关于函数指针的一些问题,其中将 char* 转换为 void* 可以工作,但签名应该相同,并且使用 void 而不是 char 是一个问题。