0

The code I'm working on is largely C++ but calls out using c system calls because unix. In C++ a string literal is a const char[], as far as I know because they are stored in the text segment and you don't want to modify them. If I'm going to be passing a list of arguments to say execv(), which takes char * const argv[] what's the correct way to declare it so no warnings are produced and no excessive casting occurs?

char * args[] = {"foo", "--bar", "bazz", NULL};

Is clear notation and makes sense but I think ends up with casting every literal from a const char[] to a char *. Which isn't ideal or maybe even memory safe.

char args[4][6] = {"foo", "--bar", "bazz", "\0" };

Puts all the variables in the stack, but everything else is wrong. It isn't an array of char*. NULL can't be set as the last entry. It can't be passed to another function unless that function also knows the exact dimensions. It wastes space. It doesn't accept dynamic elements easily. And it takes intense policing of the dimensions.

char arg0[] = "foo";
char arg1[] = "--bar";
char arg2[] = "baz";
char * args[] = { arg0, arg1, arg2, NULL};

Should work I think but it's a really verbose way to do this. Also it takes matching changes in two locations to update which is less than ideal for maintenance.

What's the right way to do this?

davolfman
  • 266
  • 1
  • 9
  • The type of a string literal is `const char[N]` – NathanOliver Sep 30 '21 at 17:15
  • Use a cast to suppress the warning. Despite the declaration, `execv()` doesn't modify any of the arguments, so this is safe. – Barmar Sep 30 '21 at 17:23
  • 1
    See https://stackoverflow.com/questions/10456043/why-is-argv-parameter-to-execvp-not-const – Barmar Sep 30 '21 at 17:25
  • It is common usage to pass string literals in the command arguments array of `execv`, so it can be assumed not to modify the contents of the string literals. I do not know why it doesn't declare the array as `const char * const argv[]`, but it's probably because string literals are not `const` qualified in C for historical reasons, even though they are not modifiable. – Ian Abbott Sep 30 '21 at 17:26
  • 1
    Does it modify the chars? If it modifies the chars then you need the last one. If it DOESN'T modify the chars then the cast really is the best option. Although maybe you can cast the entire array `const char *[]` to `(char**)` instead of casting each element – user253751 Sep 30 '21 at 17:26
  • I was hoping for an answer on the general case if I ever encounter it. Being able to to it wrong for execv*() because there's explicit permission in the documentation wouldn't help then. Also we've got that behind a thin wrapper so I wouldn't expect anyone else to know that. – davolfman Sep 30 '21 at 17:35

0 Answers0