4

I have a method that is having the following signature:

size_t advanceToNextRuleEntryRelatedIndex( size_t index, size_t nStrings, char const *const *const strings)

How do I interpret this: char const *const *const strings?.

Thanks, Pavan.

Faisal
  • 361
  • 1
  • 6
Pavan Dittakavi
  • 3,013
  • 5
  • 27
  • 47
  • 3
    from right to left, strings is a constant pointer pointing to a constant pointer pointing to const character set ? – Arunmu Dec 09 '15 at 09:17
  • 1
    Have you done any research on how C declarations are formed? – Angew is no longer proud of SO Dec 09 '15 at 09:20
  • 2
    @Pavan You should probably start from this. http://stackoverflow.com/questions/4949254/const-char-const-versus-const-char – Arunmu Dec 09 '15 at 09:24
  • Cool. The more const's the more professional the code, according to Scott Meyers. For my taste one const is missing - before char. Could be: 'const char const *const *const strings' :-) – Valentin H Dec 09 '15 at 13:44

3 Answers3

5
char const *const *const strings
 ^    v    ^  v   ^  v
 |    |    |  |   |  |
 +-----    +--+   +--+

so basically it means all pointers and the strings that the pointers point to are constant, meaning the function cannot modify the passed strings in any way (except if it gets casted).

e.g.

char* p[] = {"string1","string2"};‍

which will decay into char**

when passed to

int n = 0; 
advanceToNextRuleEntryRelatedIndex( n, 2, p);
palapapa
  • 573
  • 2
  • 5
  • 25
AndersK
  • 35,813
  • 6
  • 60
  • 86
  • const refers fo the declaration which follows const, not which precedes. – Valentin H Dec 09 '15 at 12:27
  • 5
    @ValentinHeinitz That is incorrect. `const` refers to the type on the left. Only in the special case where there is nothing to the left of `const`, `const` will refer to the type on the right. `int const *p` is a non-const pointer to a constant integer. `const int *p` is the same. `const int const *p` has one redundant `const`. `int * const p` is a constant pointer to non-constant integer. See [C & C++ conventions for const](https://en.wikipedia.org/wiki/Const_%28computer_programming%29). It's easy to misundestand `const` when `const int` and `int const` are both valid. – sendaran Dec 09 '15 at 14:43
  • 1
    @sendaran yes, for that reason I stopped using const on the left side when possible, i find it more consistent that way and works fine with typedefs – AndersK Dec 09 '15 at 17:08
2

In char const *const *const strings, strings is a pointer to a char pointer. Without the const qualifiers it would look like this:

char **strings;

The const qualifiers prohibit modifying the dereferenced value at the particular level of dereferencing:

**strings = (char) something1; // not allowed because of the first const
*strings = (char *) something2; // not allowed because of the second const
strings = (char **) something3; // not allowed because of the third const

In other words, the third const says that the pointer itself is immutable, the second const says that the pointed-to pointer is immutable and the first says that the pointed-to character is immutable.

Blagovest Buyukliev
  • 42,498
  • 14
  • 94
  • 130
1

The key-word const makes the declaration after this key-word to a constant. The code explains better than words:

/////// Test-code. Place anywhere in global space in C/C++ code, step with debugger
char a1[] = "test1";
char a2[] = "test2";

char *data[2] = {a1,a2};

// Nothing const, change letters in words, replace words, re-point to other block of words
char **string = &data[0]; 

// Can't change letters in words, but replace words, re-point to other block of words
const char **string1 = (const char **) &data[0];
// Can neither change letters in words, not replace words, but re-point to other block of words
const char * const* string2 = (const char * const*) &data[0];
// Can change nothing, however I don't understand the meaning of the 2nd const
const char const* const* const string3 = (const char const* const* const ) &data[0];


int foo()
{

    // data in debugger is:               {"test1","test2"}
    **string = 'T';         //data is now {"Test1","test2"}
    //1 **string1 = 'T';    //Compiler error: you cannot assign to a variable that is const (VS2008)
    *string1=a2;            //data is now {"test2","test2"}
    //2 **string2='T';      //Compiler error: you cannot assign to a variable that is const (VS2008)
    //3 *string2=a2;        //Compiler error: you cannot assign to a variable that is const (VS2008)
    string2=string1;

    //4 **string3='T';      //Compiler error: you cannot assign to a variable that is const (VS2008)
    //5 *string3=a2;        //Compiler error: you cannot assign to a variable that is const (VS2008)
    //6 string3=string1;    //Compiler error: you cannot assign to a variable that is const (VS2008)
    return 0;
}

static int dummy = foo();

/////// END OF Test-code
Valentin H
  • 7,240
  • 12
  • 61
  • 111
  • Actually I wanted to unvote this answer, but I cant' now, because 5 mins passed. This says "after this key-word " when in fact it's "before". Even this example says it: – Roman Feb 11 '18 at 16:54
  • // Can neither change letters in words, not replace words, but re-point to other block of words const char * const* string2 = (const char * const*) &data[0]; – Roman Feb 11 '18 at 16:54