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
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
You are not supposed to do that kind of conversion, because the types are not compatible.
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.
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 } ;
const
Types in C and C++ are read from right to left. So if you have:
char *
: pointer to charchar 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 charchar * 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 pointerIt 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) ;
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...)
You need to make a second array, which is NULL
-terminated (because fts()
's first argument is argv).
E.g.
char *const buf2[2] = { buf, NULL };
fts(buf2);
I'm assuming you're talking about fts_open
:
FTS *fts_open(char * const *path_argv, int options,
int (*compar)(const FTSENT **, const FTSENT **));
What it's wanting of you is an array of const char*
pointers, ie. an array of strings. The const
is there just to tell you that it's not going to modify your strings, and gives you the opportunity to pass const
strings.
Non-const
variables can be treated as const
, however you shouldn't usually treat them the other way around.
The first argument is just like argv
passed to main
, you could just have:
char *path_argv[] = { "/first_path/", "/second_path/", NULL };
It's important that the last element is NULL
to indicate the end of the array.
Note also that path_argv
could also be declared as:
char **path_argv
OR*
char * const *path_argv
Any of these are suitable types to be passed as the first argument to fts_open
. You do, however, obviously have to initialize it differently than the above, but those are other ways you can declare path_argv
. I made that unclear previously.
And then just fts_open(path_argv, options, compar)
, where options
is your options, and compar
is your compare function.