联机帮助页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
...