Dead Beetle
Dead Beetle

Reputation: 111

How to declare a pointer to pointer to constant in C++?

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

Answers (2)

Galik
Galik

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

M.M
M.M

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

Related Questions