Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting char * to char * const *

Tags:

c

linux

pointers

Do excuse me to the basic"ness" of this question. I am at a loss with pointers at times. I have a char * but I need to convert it to a char * const * to be able to correctly use it in the fts() function. How do i do that?

Thanks

like image 607
Lipika Deka Avatar asked Nov 10 '11 02:11

Lipika Deka


People also ask

Can const char * Be Changed?

const char* const says that the pointer can point to a constant char and value of int pointed by this pointer cannot be changed.

What is the difference between const char * and char * const?

The difference is that const char * is a pointer to a const char , while char * const is a constant pointer to a char . The first, the value being pointed to can't be changed but the pointer can be. The second, the value being pointed at can change but the pointer can't (similar to a reference).

What is a const char * in C++?

const char *ptr : This is a pointer to a constant character. You cannot change the value pointed by ptr, but you can change the pointer itself.

What is const char * str?

The const char *Str tells the compiler that the DATA the pointer points too is const . This means, Str can be changed within Func, but *Str cannot. As a copy of the pointer is passed to Func, any changes made to Str are not seen by main....


1 Answers

You are not supposed to do that kind of conversion, because the types are not compatible.

About pointers and pointers to pointers

char * is a pointer to a string of characters, whereas char ** is an pointer to a pointer to a string of characters. (the const is a bonus). This probably means that instead of supplying a string of characters, you should provide an array of string of characters.

Those two things are clearly incompatible. Don't mix them with a cast.

About the fts_* API

To find the solution to your problem, we need to read the fts_* function API (e.g. at http://linux.die.net/man/3/fts), I see that:

FTS *fts_open(char * const *path_argv, int options,
          int (*compar)(const FTSENT **, const FTSENT **));

with your char * const * parameter path_argv, the description explains:

[...] If the compar() argument is NULL, the directory traversal order is in the order listed in path_argv for the root paths [...]

which confirms that the fts_open function is really expected a collection of paths, not one only path.

So I guess you need to pass to it something like the following:

char *p[] = { "/my/path", "/my/other/path", "/another/path", NULL } ;

About the const

Types in C and C++ are read from right to left. So if you have:

  • char * : pointer to char
  • char const * : pointer to const char (i.e. you can't modify the pointed string, but you can modify the pointer)
  • const char * : the same as char const *
  • char * const : const pointer to char (i.e. you can modify the pointed string, but you can't modify the pointer)
  • char ** : pointer to pointer to char
  • char * const * : pointer to const pointer to char (i.e. you can modify the pointer, and you can modify the strings of char, but you can't modify the intermediary pointer

It can be confusing, but reading them in the right-to-left order will be clear once you are more familiar with pointers (and if you programming in C or C++, you want to become familiar with pointers).

If we go back to the initial example (which sends a bunch of warnings on gcc with C99) :

char ** p = { "/my/path", "/my/other/path", "/another/path", NULL } ;

I played with the API, and you can feed it your paths two ways:

    char * p0 = "/my/path" ;
    char * p1 = "/my/other/path" ;
    char * p2 = "/another/path" ;

    /* with a fixed-size array */
    char * pp[] = {p0, p1, p2, NULL} ;

    FTS * fts_result = fts_open(pp, 0, NULL);

Edit 2011-11-10: snogglethorpe rightfully commented this solution is not a C89 valid solution, even if it compiles successfully with gcc (excluding pendantic + C89 flags). See Error: initializer element is not computable at load time for more info on that

or:

    /* with a malloc-ed array */
    char ** pp = malloc(4 * sizeof(char *)) ;
    pp[0] = p0 ;
    pp[1] = p1 ;
    pp[2] = p2 ;
    pp[3] = NULL ;

    FTS * fts_result2 = fts_open(pp, 0, NULL);
    free(pp) ;

Edit

After reading others answers, only two of them (mkb and moshbear) avoid the "just cast the data" error.

In my own answer, I forgot the NULL terminator for the array (but then I don't know the Linux API, nor the fts_* class of functions, so...)

like image 117
paercebal Avatar answered Sep 28 '22 07:09

paercebal