在 C 中使用 qsort 时的警告

Posted

技术标签:

【中文标题】在 C 中使用 qsort 时的警告【英文标题】:Warning when using qsort in C 【发布时间】:2011-02-03 10:31:03 【问题描述】:

我写了我的比较函数

int cmp(const int * a,const int * b)
 
   if (*a==*b)
   return 0;
else
  if (*a < *b)
    return -1;
else
    return 1;

我有我的声明

int cmp (const int * value1,const int * value2);

我在我的程序中这样调用 qsort

qsort(currentCases,round,sizeof(int),cmp);

当我编译它时,我收到以下警告

warning: passing argument 4 of ‘qsort’ from incompatible pointer type
/usr/include/stdlib.h:710: note: expected ‘__compar_fn_t’ but argument is of type ‘int
(*)(const int *, const int *)’

该程序运行良好,所以我唯一担心的是为什么它不喜欢我使用它的方式?

【问题讨论】:

***.com/questions/2228695/… 只是一个更简单的 cmp 实现的建议;而不是 if/else 的东西,你可以只使用减法。 @nategoose:除非你想引入讨厌的整数溢出错误。 【参考方案1】:

cmp 函数的原型必须是

int cmp(const void* a, const void* b);

您可以在调用 qsort 时将其强制转换(不推荐):

qsort(currentCases, round, sizeof(int), (int(*)(const void*,const void*))cmp);

或将 void 指针转换为 cmp 中的 int 指针(标准方法):

int cmp(const void* pa, const void* pb) 
   int a = *(const int*)pa;
   int b = *(const int*)pb;
   ...

【讨论】:

技术上第一个是未定义的行为。无法保证您的实现的调用约定通过 const int* 的方式与通过 const void* 的方式相同。在实践中,我希望它会好起来的。显然 GCC 也希望如此,因为这只是一个警告。 使用演员表的方法是完全不可接受的,即使它看起来“有效”。 @AndreyT:你还有什么建议?编写自己的快速排序? (注意这是C,不是C++,不能用std::sort。) @KennyTM:我认为 AndreyT 在您的回答中是指第一种方法中的演员,而不是第二种方法。对于第二个,你当然可以做int *the_a = pa; int a = *the_a; 等,它不使用演员表。 @KennyTM:我的建议是使用参数转换,就像您在第二个建议中所做的那样。这是唯一的方法。【参考方案2】:

根据手册页,__compar_fn_t 定义为:typedef int(*) __compar_fn_t (const void *, const void *)

您的cmp 指定int* 参数。它不喜欢那样,而只是作为警告列出。

【讨论】:

那是因为 void* 可以隐式转换为任何其他类型的指针。至少在 C 中,C++ 有一些问题。 您在看哪个手册页? qsort 的那个没有提到__compar_fn_t

以上是关于在 C 中使用 qsort 时的警告的主要内容,如果未能解决你的问题,请参考以下文章

使用 printf 时的警告 [重复]

qsort 的第四个参数的“不兼容的指针类型”编译器警告

为啥 C++/CLI 编译器不为过时的属性调用生成警告?

在C ++ Builder中编译Boost库时的警告

VSCode在打印输出sizeof()时的警告

动态分配内存时的警告