Convert char * to char * const *

Excuse me for the main "problem" of this question. Sometimes I disagree with pointers. I have a char * , but I need to convert it to char * const * in order to be able to use it correctly in the fts () function. How to do it?

thanks

+4
source share
3 answers

You should not do such a conversion because the types are incompatible.

About pointers and pointers of pointers

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

These two things are clearly incompatible. Do not mix them with cast.

About fts_ * API

To find a solution to your problem, we need to read the fts_ * API (e.g. 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 the parameter char * const * path_argv , the description explains:

[...] If compare () is NULL, the directory traversal order is in the order specified in path_argv for root paths [...]

which confirms that the fts_open function really expects a set of paths, not just one path.

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

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

About const

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

  • char * : pointer to char
  • char const * : pointer to const char (i.e. you cannot change the specified string, but you can change the pointer)
  • const char * : same as char const *
  • char * const : const pointer to char (i.e. you can change the pointed line, but you cannot change the pointer)
  • char ** : pointer to a pointer to char
  • char * const * : pointer to a constant pointer to char (i.e. you can change the pointer, and you can change the char strings, but you cannot change the broker pointer

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

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

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

I played with the API, and you can feed it your own ways in 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 on this solution, is not a valid C89 solution, even if it successfully compiles with gcc (excluding pendantic + C89 flags). See Error: The initialization element is not computable at boot time for more information on this.

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 the other answers, only two of them ( mkb and moshbear ) avoid the data error.

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

+10
source

You need to make a second array that is NULL -terminated (because fts fts() first argv argument).

eg.

 char *const buf2[2] = { buf, NULL }; fts(buf2); 
+2
source

I assume you are talking about fts_open :

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

What he wants from you is an array of const char* pointers, i.e. array of strings. const is just to tell you that it is not going to change your lines and gives you the ability to pass const lines.

Non- const variables can be thought of as const , but usually you should not treat them differently.

The first argument is similar to argv passed to main , you can simply:

 char *path_argv[] = { "/first_path/", "/second_path/", NULL }; 

It is important that the last NULL element indicates the end of the array.

Note that path_argv can also be declared as:

 char **path_argv 

OR *

 char * const *path_argv 

Any of these is a suitable type that should be passed as the first argument to fts_open . However, you obviously need to initialize it differently than the above, but these are other ways you can declare path_argv . I made it previously unclear.

And then just fts_open(path_argv, options, compar) , where options are your options and compar is your comparison function.

+2
source

Source: https://habr.com/ru/post/1380504/


All Articles