Why I can't pass an argument of type 'char* const *' to a function which expected 'const char* const*' as it's argument?

Viewed 411

I am writing a function using fork and execv to replace system() and popen() in a project. I found that although execv won't change the content of the command array, it declare it's second argument as char * const argv[], which can actually change the content of char*. Thus I decide to declare my function like this:int execute_cmd(const char* const cmd[]) so that both the pointer to char is const and the content the const pointer point to is const(Sorry I know this state is confusing but I tried) However, when I call it in this way:

void execute_cmd(const char* const cmd[])
{
    for (int i = 0; cmd[i]; i++)
    {
        printf("%s ", cmd[i]);
    }
}

int main()
{
    char* const cmd[] = {"ls", "-al", 0};
    execute_cmd(cmd);
    return 0;
}

there is a complie error saying that:

test.c:21: warning: passing argument 1 of ‘execute_cmd’ from incompatible pointer type

test.c:10: note: expected ‘const char * const*’ but argument is of type ‘char * const*’

I wonder why this happen because IMO an formal argument with const can take an non-const variable as it's actual parameter, such as:

void printInt(const int);
//which can call like this
int a=10;
printInt(a);

And I think initialize a const variable with a non-const variable is very common, So why this function work but my execute_cmd() didn't? Did I miss something importent with the const? I have search "char * const * and const char* const *" and "const formal argument with non-const actual parameter" such things but haven't get something very useful, I will also appreciate if anyone can give me an idea about the correct key-work to this question. I am not a native English speaker so if there are some grammar problem please forgive me.

1 Answers

I wonder why this happen because IMO an formal argument with const can take an non-const variable as it's actual parameter

It is more like "a formal parameter with const can take an non-const variable as it's actual argument."

const char* const cmd_paramter[] is like an "array of const pointer to const char".

char* const cmd_argument[] is an "array of const pointer to char".

Notice the type of the array elements differ: const char * vs. char *.

Same problem with simpler code: "expected 'char *' but argument is of type 'const char *'"

void foo(char *bob);
const char *alice = "Alice";

// Bad, as `foo()` needs to be able to write `*bob`, yet alice point to `const` data.
foo(alice);  

Further, cmd array elements should be of type const char * to prevent writing a string literal.

    // char* const cmd[] = {"ls", "-al", 0};
    const char* const cmd[] = {"ls", "-al", 0};
Related