Search code examples
cpointerssyntaxconstantsdeclaration

Using const keyword in c


I have been looking at a source code, and i came across this code

    static char const *const delimit_method_string[] =
    {
        "none", "prepend", "separate", NULL
    };

I thought I knew the meaning of const keyword in the C language but after seeing this syntax I am confused as I can't decode the meaning of the syntax, so I wanted to know the meaning of using const like this I searched internet I saw some questions like this in stackoverflow that are,

  1. Meaning of two const in C/C++ signature
  2. Double const declaration

But still I don't understand what's the meaning of the syntax in that code snippet, may be that because I am not good enough with fundamentals of C but I really like to improve it.

So I wrote some code to know how that syntax works, this is what I tried:

    #include <stdio.h>
    
    int main()
    {
        char a = 'A';
        char b = 'B';
        char const * const ptr = &a;

        ptr = &b;

        printf("a is %c\n", *ptr);
        printf("a is %c", a);
    
        return 0;
    }

I got this output, that somewhat I expected.

$ gcc test.c
test.c: In function 'main':
test.c:9:13: error: assignment of read-only variable 'ptr'
    9 |         ptr = &b;
      |  

                    ^

I changed the code and tested again,

    #include <stdio.h>
    
    int main()
    {
        char a = 'A';
        char b = 'B';
        char const const *ptr = &a;
    
        ptr = &b;

        printf("a is %c\n", *ptr);
        printf("a is %c", a);
    
        return 0;
    }

this time the output is not what I expected,

$ ./a.exe
a is B
a is A

I really appreciate if someone can explain what is the correct way of using const in C and also how the syntax in first code snippet works.


Solution

  • This declaration

    static char const *const delimit_method_string[] =
    {
      "none", "prepend", "separate", NULL
    };
    

    declares an array with the name delimit_method_string of pointers to string literals.

    In C opposite to C++ string literals have types of non-constant character arrays. Nevertheless you may not change a string literal. Any attempt to change a string literal results in undefined behavior. So it is better to declare pointers to string literals the following way as for example

    const char *s = "Hello";
    

    So you could declare the above array like

    static char const * delimit_method_string[] =
    {
      "none", "prepend", "separate", NULL
    };
    

    But the programmer who declared this array also wanted to declare at as a constant array. That is he wanted that its elements can not be changed.

    For the declaration above you can write for example

    delimit_method_string[0] = "all";
    

    To prevent such a changing elements of the array must be constant. To do this you need to write

    static char const * const delimit_method_string[] =
    {
      "none", "prepend", "separate", NULL
    };
    

    Now the elements of the array that have the pointer type const char * are constant due to the second qualifier const.

    Tom make it more clear consider the following declarations.

    char *p;
    

    This declaration declares a non-constant pointer to a non-constant object of the type char.

    const char *p;
    

    This declaration declares a non-constant pointer to a constant object of the type char.

    const char * const p;
    

    This declaration declares a constant pointer to a constant object of the type char.

    The last declaration may be rewritten like

    const char ( * const p );
    

    As for this your declaraion

    char const const *ptr = &a;
    

    then on of the two qualifiers const is redundant because the both refer to the type specifier char.