Domanda

Ho un problema con scandir () : la manpage lo contiene come prototipo:

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

Quindi ho questo:

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

Ed ecco la chiamata:

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

Alla fine il compilatore dice questo:

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

Il compilatore è gcc-4.3.2 , i miei CFLAGS sono i seguenti:

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

Qual è il significato di questo avviso? La dichiarazione di RubyCompare sembra corretta per me e oltre all'avvertimento il codice funziona completamente.

È stato utile?

Soluzione

In realtà, non esiste un vincolo tale da non poter passare un puntatore a una funzione incorporata. La parola chiave inline serve solo come suggerimento al compilatore per inlineare le chiamate quando può.

Il problema è che la manpage di scandir () è un po 'fuorviante. Il prototipo per il quarto parametro è in realtà int (* cmp) (const void *, const void *).

Pertanto è necessario modificare il codice in questo modo:

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

In realtà non sono sicuro del motivo per cui stai scrivendo questa funzione, perché puoi utilizzare la funzione di confronto alphasort fornita:

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

Altri suggerimenti

Questo prototipo è stato effettivamente modificato nella recente versione di GNU libc per riflettere lo standard POSIX.

Se si dispone di codice su cui si desidera lavorare sia con il codice vecchio che con quello nuovo, utilizzare la macro __GLIBC_PREREQ in modo simile

#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

...

Gli stai dando un puntatore a una funzione inline? Non ha senso, in realtà mi chiedo che si compili anche solo con un avvertimento.

MODIFICA : Chris sopra ha ragione, la parola chiave incorporata viene ignorata silenziosamente quando non ha senso / non è applicabile.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top