tags:

views:

1004

answers:

2

I often use the execv() function in C++ but if some of the arguments are in C++ strings. It annoys me that I cannot do this:

const char *args[4];

args[0] = "/usr/bin/whatever";
args[1] = filename.c_str();
args[2] = someparameter.c_str();
args[3] = 0;

execv(args[0], args);

This doesn't compile because execv() takes char *const argv[] which is not compatible with const char * so I have to copy my std::strings to character arrays using strdup() which is a pain.

Does anyone know the reason for this ?

+1  A: 

const is a C++ thing - execv has taken char * arguments since before C++ existed.

You can use const_cast instead of copying, because execv doesn't actually modify its arguments. You might consider writing a wrapper to save yourself the typing.

Actually, a bigger problem with your code is that you declared an array of characters instead of an array of strings.

Try: const char* args[4];

Jonathan
Oh, I meant to type const char *, either I typed it wrong or stack overflow has chomped my asterisk. I'll edit the question.
Adam Pierce
execv will not accept const char *arg[] - at least not with g++, but thanks for the answer, I did consider casting to non-const but I did not know if that was safe.
Adam Pierce
A C compiler will allow you to pass a const char* to execv, but it will issue a warning. For a C++ compiler, though, you need to use const_cast.
Adam Rosenfield
"const is a C++ thing" -- const was a C thing, standardized in C before being standardized in C++. "execv has taken char * arguments since before C++ existed" -- but after C existed (but before C was standardized).
Windows programmer
"A C compiler will allow you to pass a const char* to execv, but it will issue a warning." <- this is equivalent to not allowing it. in C and C++, there is no difference between a warning and an error (c++ and C don't know the difference): both are diagnostics.
Johannes Schaub - litb
+9  A: 

The Open Group Base Specifications explains why this is: for compatibility with existing C code. Neither the pointers nor the string contents themselves are intended to be changed, though. Thus, in this case, you can get away with const_cast-ing the result of c_str().

Quote:

The statement about argv[] and envp[] being constants is included to make explicit to future writers of language bindings that these objects are completely constant. Due to a limitation of the ISO C standard, it is not possible to state that idea in standard C. Specifying two levels of const- qualification for the argv[] and envp[] parameters for the exec functions may seem to be the natural choice, given that these functions do not modify either the array of pointers or the characters to which the function points, but this would disallow existing correct code. Instead, only the array of pointers is noted as constant.

The table and text after that is even more insightful. However, Stack Overflow doesn't allow tables to be inserted, so the quote above should be enough context for you to search for the right place in the linked document.

Chris Jester-Young
I'm going to accept this answer even though Jonathan's is similar. This one is worded better in my opinion.
Adam Pierce
Thanks! I just added a bit stating that people should read on, in the quoted article; it explains the rationale even better, and how, were it not for compatibility, char const* const[] would have been vastly more preferable.
Chris Jester-Young