Why does C in contrast to C++ ban adding const-qualification to both levels of a pointer-to-pointer?

Viewed 200

I have the following situation:

A function creates an array of strings and then passes this to a bunch of other functions. These other functions should not modify neither pointers pointed to by the outer pointer nor the strings themselves, so I made them const.

Minimal example:

void function(const char * const *arr) {
    /* Do something useful */
}

int main(void) {
    char **x;
    /* fill x and *x */
    function(x);
}

When compiling with gcc or clang this gives me a warning, that x is converted to an incompatible pointer type.

While I understand why the pointer type is incompatible if I remove the second const in the parameter list of function (explained here: Why does passing char** as const char** generate a warning?), I do not understand why it is incompatible with the const.

Compiling with a c++-Compiler does not give me the warning (See comparison here: https://gcc.godbolt.org/z/YND5U7)

1 Answers

I do not understand why it is incompatible with the const.

Note: const1, const2 defined for clarity to distinguish the two.

In C, the const2 in const1 char * const2 *arr is the qualifier x optionally matches. const2 say that function(const1 char * const2 *arr) has a contract with the calling code, it will not change what arr points to. arr points to a const1 char *. arr can be const1 char ** or const1 char * const2 *.

In main(), incompatible because *x points to a char * and not a const1 char *. What it points to is different than what function() expects. const1 is not part of the function() no-write contract. Instead, const1 char * is a type and that differs from char *.

At this point, I see no reason why C could not have been specified differently to allowed a char * to be treated like a const1 char * in function() - it is simply a case that C does not allow it.

#define const1 const
#define const2 const
void function(const1 char * const2 *arr) {
    // Do something useful
}

int main(void) {
    char **x = 0;
    function(x);  // bad  
    // note: expected 'const char * const*' but argument is of type 'char **'

    const char **x2 = 0;
    function(x2); // OK
}

No comment on C++

Related