【问题标题】:Pointer type mismatch warning in example from K&R C [duplicate]来自 K&R C 的示例中的指针类型不匹配警告 [重复]
【发布时间】:2009-03-20 04:45:28
【问题描述】:

可能重复:
Problem compiling K&R example

最近我一直在学习 K&R 的 C 编程语言。

在第 5.11 节中,他们介绍了指向函数的指针,并且在输入示例之后——快速排序实现,我们提供了指向我们想要使用的比较函数的指针——我收到了来自编译器的警告:指针类型不匹配在条件表达式中。 (我的编译器是 OS X 10.5.6 上的 gcc 4.0.1)

示例中触发警告的行是:

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

程序执行时没有段错误,但我喜欢尽可能消除所有警告,或者至少了解它们的原因。

numcmp 的函数声明如下:

 int numcmp(char *, char *);

但是根据手册页,stcmp 有这个签名:

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

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

【问题讨论】:

  • Dana,查看Problem compiling K&R example,您可能会在那里找到问题的答案。如果您不知道,请告诉我们。
  • 埃迪指着一个骗子。我投票结束我自己的问题,但我认为所有者可以通过一种方式立即关闭它。

标签: c kernighan-and-ritchie


【解决方案1】:

虽然您可以将 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。

【讨论】:

  • 另一种选择是将三元表达式更改为以下内容: numeric ? (int ()(void *, void *))numcmp : (int ()(void *, void *))strcmp);因此,只需将两个不同的函数分别传递给 qsort。这也将避免编译器给出的任何警告
【解决方案2】:

简答:K&R 不知道 C。

长答案:他们受到以下事实的阻碍:当他们开始时,没有人知道 C,所以他们在进行过程中有点弥补。

(稍微)不那么轻率的长答案形式:自从编写 K&R 以来,该语言已经发展了很多(有人会说改变了),但除非您获得带有动态示例变形,您的 K&R 副本中的示例不会跟上“新的和认可的”(“现在有了更多的 ANSI!”)语言。

【讨论】:

    【解决方案3】:

    尝试诊断它的一种方法是看看如果用 ?: 替换表达式会发生什么情况。

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

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

    【讨论】:

      猜你喜欢
      • 2016-09-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-06-09
      • 1970-01-01
      • 2023-04-03
      相关资源
      最近更新 更多