联机帮助页scandir()原型怪异

时间:2020-03-06 14:50:54  来源:igfitidea点击:

我的scandir()有问题:联机帮助页包含以下内容作为原型:

int scandir(const char *dir, struct dirent ***namelist,
  int (*filter)(const struct dirent *),
  int (*compar)(const struct dirent **, const struct dirent **));

因此,我有这个:

static inline int
RubyCompare(const struct dirent **a,
  const struct dirent **b)
{
  return(strcmp((*a)->d_name, (*b)->d_name));
}

这是电话:

num = scandir(buf, &entries, NULL, RubyCompare);

最后,编译器这样说:

warning: passing argument 4 of ‘scandir’ from incompatible pointer type

编译器是gcc-4.3.2,我的CFLAGS如下:

-Wall -Wpointer-arith -Wstrict-prototypes -Wunused -Wshadow -std=gnu99

此警告是什么意思? RubyCompare的声明对我来说似乎是正确的,除了警告之外,代码还可以完全正常工作。

解决方案

我们要给它一个内联函数的指针吗?那没有道理,实际上我想知道它甚至只带有警告就可以编译。

编辑:上面的克里斯是正确的,当inline关键字没有任何意义/不适用时,它将被默默地忽略。

实际上,不存在不能将指针传递给内联函数的约束。 inline关键字仅作为编译器可以进行内联调用的提示。

问题在于scandir()的联机帮助页有点误导。第四个参数的原型实际上是int(* cmp)(const void *,const void *)。

因此,我们需要像这样更改代码:

static inline int RubyCompare(const void *a, const void *b)
{
    return(strcmp((*(struct dirent **)a)->d_name, 
                  (*(struct dirent **)b)->d_name));
}

我实际上不确定为什么要编写此函数,因为可以使用提供的alphasort比较函数:

num = scandir(buf, &entries, NULL, alphasort);

实际上,此原型已在GNU libc的最新版本中进行了更改,以反映POSIX标准。

如果我们有要使用新旧代码的代码,请使用__GLIBC_PREREQ宏,例如

#define USE_SCANDIR_VOIDPTR 
#if defined( __GLIBC_PREREQ  )
# if  __GLIBC_PREREQ(2,10)
#  undef USE_SCANDIR_VOIDPTR
# endif
#endif

#ifdef USE_SCANDIR_VOIDPTR
 static int RubyCompare(const void *a,  const void *b)
#else 
 static int RubyCompare(const struct dirent **a,  const struct dirent **b)
#endif

...