Search code examples
cgcc-warninggcc4

Declaring and initializing a completely `const` `char *argv[]`


I tried assigning the argv value to a constant pointer, believing that it's safe to assign a non-const to a const variable.

Unfortunately gcc complained:

> make CFLAGS=-Wall mein
cc -Wall    mein.c   -o mein
mein.c: In function ‘main’:
mein.c:5:30: warning: initialization from incompatible pointer type [-Wincompatible-pointer-types]
  const char *const*const a = argv + 1;
                              ^~~~
mein.c:5:26: warning: unused variable ‘a’ [-Wunused-variable]
  const char *const*const a = argv + 1;

The corresponding C source looks like this:

2021-07-08 13:49                      mein.c                      Page 1


    1   #include <stdlib.h>
    2   
    3   int main(int argc, char *argv[])
    4   {
    5       const char *const*const a = argv + 1;
    6       return 0;
    7   }

I believe my declaration says a is a constant pointer to an array of constant pointers pointing to constant strings. I also believe that char *argv[] is equivalent to char **argv.

The question is: Am I wrong, or is gcc wrong?


Solution

  • For initialization, C 2018 6.7.9 11 says:

    … the same type constraints and conversions as for simple assignment apply…

    For simple assignment, 6.5.16.1 1 says:

    One of the following shall hold: … the left operand has atomic, qualified, or unqualified pointer type, and (considering the type the left operand would have after lvalue conversion) both operands are pointers to qualified or unqualified versions of compatible types, and the type pointed to by the left has all the qualifiers of the type pointed to by the right;…

    For this purpose, the “left operand” is the a with type const char * const * const and the “right operand” is argv + 1 with type char **. The type the left operand points to is const char * const, and the type the right operand points to is char *.

    The left operand is a qualified version of const char *, and the right operand is an unqualified version of char *. Then this initialization conforms to the constraints if the former type (const char *) is compatible with the latter (char *).

    6.7.6.1 2 says:

    For two pointer types to be compatible, both shall be identically qualified and both shall be pointers to compatible types.

    So const char * and char * are compatible if const char and char are compatible.

    6.7.3 11 says:

    For two qualified types to be compatible, both shall have the identically qualified version of a compatible type; the order of type qualifiers within a list of specifiers or qualifiers does not affect the specified type.

    Since const char is const qualified and char is not, these are not compatible types.

    Therefore, this initialization does not conform to the constraints of the C standard.

    The question is: Am I wrong, or is gcc wrong?

    GCC is right, you are wrong.