TIP: Click on subject to list as thread! ANSI
echo: os2prog
to: Jani Patanen
from: Thomas Seeling
date: 1996-10-24 13:35:00
subject: Pointer to a pointer to a pointer a

Hallo, Jani!

*** Am 19. Oktober 1996 um 12:09 schrieb Jani Patanen an All:

 JP> scandir.c:45: request for member `d_name' in something not a structure or
 JP> union

 JP> scandir(const char *dirname, struct dirent ***namelist,
 JP>         int (*select)(struct dirent *),
 JP>         int (*compar)(const void *, const void *))

 JP> namelist=(PVOID) NULL;
*namelist=NULL;

"namelist" is a local variable, since C does not support call by
reference, only call by value. If you have to modify a parameter, pass a
pointer to it to the function.

I.e. if you want to modify a char *:

void change(char **x) {
  *x=malloc(100);
  strcpy(*x,"Hallo");
}

void testit(void) {
  char *what;

  change(&what);
}

 JP>     namelist = (struct dirent ***) realloc
You modify the local variable namelist, which has no effect after the
function returns. You want to do something like

*namelist=realloc(...);

When dealing with 2-dimensional arrays, you first have to allocate memory
for the row pointers, then for each element in each row you have to
allocate further memory.

*namelist=malloc(rowcount*sizeof(*nanelist));

*namelist if of type dirent **.

Afterwards, you have to allocate memory for each element:

(*namelist)[0]=malloc(columncount*sizeof((*namelist)[0]));

_Then_ you can use the allocated memory, ie. assign a dirent * to
(*namelist)[0][0] etc.

In this special case, where the runtime function returns a struct pointer,
I strongly recommend copying the contents of the struct to private memory
you allocated yourself. In most cases, the contents of the struct the
returned pointer points to will be destroyed by the next call to the same
function.

You should not mess around with dirent ***; just return the pointer to the
start of the array as function result. The return value is then either NULL
(failure or nothing matched) or a dirent **, i.e. an array of dirent *.

If your c runtime library has support which hides the underlying API you
should not use the API calls directly. There may be advantages or must-be
(standalone DLL without runtime), but in general use the c runtime, not the
OS API.

typedef struct dirent **DirectoryArray;

DirectoryArray readthedir(const char *what, int *count) {
  DirectoryArray thedir=NULL;
  struct dirent *e;
  DIR           *dir;
  int            cnt=1;

  dir = opendir (what);
  if (count)
    *count=0;
  if (dir == NULL)
    return NULL;
  while ((e = readdir (dir)) != NULL) {
    thedir=realloc(thedir,cnt+1);
    thedir[cnt]=malloc(sizeof *e);
    *thedir[cnt]=*e; /* or memcpy(...) */
    printf ("%s\n", e->d_name);
    ++cnt;
  }
  thedir[cnt]=NULL; /* mark end of array */
  closedir (dir);
  if (count)
    *count=cnt;
  return thedir;
}

My example either receives the count of entries in int *count, or you can
march along the array and stop when encountering the NULL pointer at the
end. Call the function with "readthedir(...,NULL)" for this
usage.


Tschau...Thomas

--- E3-32/1.11-32/2.50+
* Origin: Die TeX-Box +49-6034-930021 V.34 -930022 ISDN 24h (2:244/1130.42)
SEEN-BY: 50/99 270/101 620/243 625/160 711/401 409 410 413 430 808 809 934
SEEN-BY: 711/955 712/407 515 624 628 713/317 800/1
@PATH: 244/1130 24/999 888 396/1 270/101 712/515 711/808 934

SOURCE: echomail via fidonet.ozzmosis.com

Email questions or comments to sysop@ipingthereforeiam.com
All parts of this website painstakingly hand-crafted in the U.S.A.!
IPTIA BBS/MUD/Terminal/Game Server List, © 2025 IPTIA Consulting™.