Reputation: 111
I'm trying to write a function to parse command line arguments. This is the function declaration:
void parse(int, char const **);
Just in case, I have also tried (const char)**
, const char **
, and cchar **
using a typedef const char cchar
. However, all of these (as expected, since they should all be identical) result in an error if I pass a char **
into the function, as in:
void main(int argc, char **argv) {
parse(argc, argv);
The error I get from GNU's compiler is error: invalid conversion from 'char**' to 'const char**'
and the one from Clang is candidate function not viable: no known conversion from 'char **' to 'const char **' for 2nd argument
.
I have seen such solutions suggested as declaring a pointer to a const pointer to char (const char * const *
), but I don't want either pointer to be const because I want to be able to modify the pointer so I can iterate over an argument using for(; **argv; ++*argv)
. How can I declare a "non-const pointer to non-const pointer to const char"?
Upvotes: 3
Views: 236
Reputation: 48615
The safest signature that prevents modification of the arguments whilst allowing any other const
combination to call the function is this:
parse(int argc, char const* const* argv);
That means that argv
is a pointer to a const
pointer to a const char
You can happily iterate over the parameters like this:
for(auto arg = argv + 1; *arg; ++arg)
{
if(!std::strcmp(*arg, "--help"))
return print_help();
else if(!std::strcmp(*arg, "-v") || !std::strcmp(*arg, "--verbose"))
verbose_flag = true;
// ... etc...
}
Notice there is no need to accept the variable int argc
because the array of character arrays is null terminated.
So I normally use this:
struct config
{
// program options and switches
};
config parse_commandline(char const* const* argv);
Upvotes: 5
Reputation: 141598
The function should be declared as:
void parse(int, char const * const *);
In C++, char **
can implicitly add const
at all pointer depths, so you can call it as parse(argc, argv)
.
In C, const
can only be added at the first pointer depth (this is a design defect in the language). Here is a dedicated thread. So you have to call the function as: parse(argc, (char const * const *)argv);
unfortunately.
Upvotes: 7