3

I am trying to use scandir to print a list of files in the current directory. When I try to compile, I am receiving the following errors and warnings:

warning: implicit declaration of function ‘scandir’ [-Wimplicit-function-declaration]
error: ‘alphasort’ undeclared (first use in this function)
note: each undeclared identifier is reported only once for each function it appears in

I am including <dirent.h>, which to my knowledge should define scandir() and all related functions. And I don't see any errors in my code:

#include <dirent.h>
...
int printFiles(){
    struct dirent **nameList;
    int numOfFiles = scandir(".", &nameList, 0, alphasort);

    //TODO print file names
    return numOfFiles;
}
....

I am running Ubuntu 12.04, and I'm compiling using gcc with the -c99 flag.

Am I simply overlooking something? I can't figure out why it's failing to compile.

Jonathan Leffler
  • 730,956
  • 141
  • 904
  • 1,278
Bluedanes
  • 35
  • 1
  • 5
  • 1
    The reason for the different messages is that the compiler knows from context that `scandir()` must be a function, but it cannot tell from the context that `alphasort()` is a function. – Jonathan Leffler Oct 18 '13 at 02:28

3 Answers3

4

If you use -std=c99, only functions that are strictly a part of the C99 standard are included by the header files. scandir() is not in the C99 standard. Therefore, you have to set a preprocessor variable to ensure that the function prototype is included. For example, the man page for scandir() indicates that setting the _BSD_SOURCE or _SVID_SOURCE preprocessor variables before you do the #include will fix the problem. Or, you can use #define _GNU_SOURCE which will in turn set quite a few different variables for you (including _BSD_SOURCE and _SVID_SOURCE).

Your code will still compile with the warning and work because C allows you to compile with implicitly defined functions, and the linker will correctly link the call to scandir() to the proper function.

Yu Hao
  • 119,891
  • 44
  • 235
  • 294
ScottKu
  • 261
  • 2
  • 6
1

what macro you use is decided by the macro in dirent.h on your own computer.usually it located in /usr/include/dirent.h.

  1. find scandir in dirent.h ,you will find the macro which make scandir Invisible.for example in my conmputer,it is "__USE_BSD ,__USE_MISC".

    #if defined __USE_BSD || defined __USE_MISC
    /* Return the file descriptor used by DIRP.  */
    extern int dirfd (DIR *__dirp) __THROW __nonnull ((1));
    
    # if defined __OPTIMIZE__ && defined _DIR_dirfd
    #  define dirfd(dirp)   _DIR_dirfd (dirp)
    # endif
    
    # ifndef MAXNAMLEN
    /* Get the definitions of the POSIX.1 limits.  */
    #  include <bits/posix1_lim.h>
    
    /* `MAXNAMLEN' is the BSD name for what POSIX calls `NAME_MAX'.  */
    #  ifdef NAME_MAX
    #   define MAXNAMLEN    NAME_MAX
    #  else
    #   define MAXNAMLEN    255
    #  endif
    # endif
    
    # define __need_size_t
    # include <stddef.h>
    
    # ifndef __USE_FILE_OFFSET64
    extern int scandir (__const char *__restrict __dir,
        struct dirent ***__restrict __namelist,
        int (*__selector) (__const struct dirent *),
        int (*__cmp) (__const void *, __const void *))
    __nonnull ((1, 2));
    # else
    #  ifdef __REDIRECT
    extern int __REDIRECT (scandir,
        (__const char *__restrict __dir,
        struct dirent ***__restrict __namelist,
        int (*__selector) (__const struct dirent *),
        int (*__cmp) (__const void *, __const void *)),
        scandir64) __nonnull ((1, 2));
    #  else
    #  define scandir scandir64
    #  endif
    # endif
    

    you know what to do now? don't be worry!it not a nice way to #define this macro directly.

  2. open file features.h(located /usr/include/features.h),search "__USE_MISC" inside,you can see codes below:

    #if defined _BSD_SOURCE || defined _SVID_SOURCE
    # define __USE_MISC 1
    #endif
    

    it tells that if"_BSD_SOURCE "or"_SVID_SOURCE"is defined,then __USE_MISC would be defined auto.

  3. consider Compatibility of you own codes,add statement below(any one or both) at start(before any statement like #include <.h>||".h") of you file which will use scandir().

    #define _BSD_SOURCE  1
    #define _SVID_SOURCE 1
    
  4. save your file and make.

0

try to #include <sys/dir.h> file to use scandir and define extern int alphasort(const void*,const void*); or extern int alphasort(); above your printFiles

also - you should link you program with standard library (hope it is already done)

Iłya Bursov
  • 23,342
  • 4
  • 33
  • 57
  • I left out some of my includes, but I was using `` `` `` and a few others. There are several others that pertain to other specific functions. I also tried putting in the defines you suggested and they didn't change anything. Any ideas? – Bluedanes Oct 18 '13 at 01:17
  • @Bluedanes check sys/dir.h is alphasort is declared here? – Iłya Bursov Oct 18 '13 at 01:19
  • 1
    `sys/dir.h` isn't in MinGW. – MD XF Feb 21 '17 at 00:12