6

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.

chqrlie
  • 131,814
  • 10
  • 121
  • 189
ABHIJITH EA
  • 308
  • 4
  • 13
  • What did you expect for the second snippet? – tstanisl Nov 27 '21 at 08:44
  • @tstanisl i thought i will get an error like before but i didn't get any – ABHIJITH EA Nov 27 '21 at 08:45
  • 2
    I don't find my 2 cents sufficient for an answer, but I always try to read the declaration backwards: so `static char const *const delimit_method_string`: `delimit_method_string` is a `const` pointer `*` which points to a `const` ((unmodifyable) `char`, which is `static`. This helps me understand it. – Dávid Tóth Nov 27 '21 at 09:09
  • 2
    @DavidTóth yeah that makes sense, Thanks for the trick:) – ABHIJITH EA Nov 27 '21 at 09:11

2 Answers2

4

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.

Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • 1
    Good explanation! You might add that `static`, `const` and `char` can appear in any order before the `*` with the same meaning. `static const char *p` and `static char const *p` are equivalent, as well as `char const static *p`, which is quite confusing :) – chqrlie Nov 27 '21 at 09:57
3
char const const *ptr = &a;

This double const does not have any special meaning as both are on the same side of the *. Additional const qualifiers are ignored by the compiler. You can write char const const const const const*ptr = &a; It is the same as char const *ptr = &a; which means:

pointer to constant character

If we change it to

char const * const ptr = &a;

It will mean:

constant pointer to constant char

Your snippet will stop to compile: https://godbolt.org/z/sM9qnv8fq

examples:

  • const int *ptr; - pointer to constant integer
  • int * const ptr; - constant pointer to integer
  • const int * const ptr; - constant pointer to constant integer

Your first example static char const *const delimit_method_string[] declares:

static array of constant pointers to constant character

BTW I personally prefer to have the first const before the type ie:

static const volatile char *const delimit_method_string[]

const char *p

0___________
  • 60,014
  • 4
  • 34
  • 74