Manpage scandir () странность прототипа - PullRequest
6 голосов
/ 28 сентября 2008

У меня проблема с 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 выглядит для меня правильным, и, кроме предупреждения, код работает полностью.

Ответы [ 3 ]

5 голосов
/ 28 сентября 2008

На самом деле, нет такого ограничения, что вы не можете передать указатель на встроенную функцию. Ключевое слово inline служит только подсказкой компилятору для встроенных вызовов, когда это возможно.

Проблема в том, что man-страница для scandir () немного вводит в заблуждение. Прототип для 4-го параметра на самом деле 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);
3 голосов
/ 15 сентября 2009

Этот прототип фактически изменился в последней версии 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

...

1 голос
/ 28 сентября 2008

Вы даете ему указатель на встроенную функцию? Это не имеет смысла, на самом деле мне интересно, что это даже компилируется только с предупреждением.

РЕДАКТИРОВАТЬ : Крис выше прав, ключевое слово inline просто игнорируется, когда оно не имеет смысла / неприменимо.

...