19

Code:

const char* const* const* foo(int bar);

I've seen double consts before which prevent the modification of the pointer too. First time i've seen triple const in my life. Wondering what its use is.

200_success
  • 7,286
  • 1
  • 43
  • 74
Learath2
  • 20,023
  • 2
  • 20
  • 30

4 Answers4

18

In your example all but the top level of indirection all const qualified.

const char            /* const qualified base level */
    *const            /* const qualified level 1 */
    *const            /* const qualified level 2 */
    *                 /* regular level 3 */
    foo(int bar);

foo is a function that accepts an int argument and returns a regular pointer.
The pointer it returns points to a const qualified pointer
which, in turn, points to another const qualified pointer
which points to const qualified char

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
pmg
  • 106,608
  • 13
  • 126
  • 198
14

If you have a multilevel pointer, you have several pointer variables. Example:

char*** foo;

is accessed like this:

| foo | pointer1 | pointer2 | string |
   |    ^     |    ^     |    ^
    \___/      \___/      \___/

You can qualify each of the four locations in memory as being const, as in the declaration

const char *const *const *const foo;

However, best avoid becoming a three star programmer.

cmaster - reinstate monica
  • 38,891
  • 9
  • 62
  • 106
  • The main (sane) use I've seen for a `char ***` is when modelling an “out” parameter that tells the caller about an array of strings. Sprinkling all those `const`s in there just makes everything more confusing… – Donal Fellows Apr 13 '14 at 17:06
  • @DonalFellows being the ``three star programmer'' who wrote this, you're right in that it is meant to pass out an array of strings. You're wrong in that it only adds confusion, though. It prevents user code from messing with that array or one of the strings it contains. – fstd Apr 14 '14 at 08:17
  • @fstd I know how to use a multi-`const` too. Still scares the horses. – Donal Fellows Apr 14 '14 at 10:53
  • @DonalFellows I wasn't explaining to you how it works, I was justifying the usage. Don't see how it's anything scary -- in contrast, omitting the const would lead to a scary situation. This is library code. – fstd Apr 14 '14 at 11:45
8

Hah - the confusion around const.

Basically, if it qualifies a pointer, then it applies to the pointer immediately to its left. For example:

char *const c;

makes c a read-only pointer to char, whereas

const char *c;

Makes c a pointer to a read-only char, though you can change where c points to.

Of course, both the pointer and what it points to can be made read-only:

const char *const c;

This makes c a read-only pointer to a read-only char. With the former declaration, you can modify *c, but you can't modify c (i.e. you can't make it point to somewhere else). With the second, you can assign to c but not to *c, and with the third, you can't modify where it points to, nor can you modify the pointed-to object.

This extends to multiple levels of indirection. For your case, you might want to regroup the const keywords with the matching pointer that they are qualifying. This is mainly a whitespaces issue, but it would be like this:

const char *const *const *foo(int bar);

Which makes foo return a pointer to a read-only pointer to a read-only pointer to a read-only char. Read that carefully: note that given this piece of code:

const char *const *const *ptr = foo(0);

Then you know that assigning to ptr is legal, but any other assignment is illegal, namely, you can't assign to *ptr, **ptr, and ***ptr.

Filipe Gonçalves
  • 20,783
  • 6
  • 53
  • 70
4

foo returns a pointer which points to a constant pointer which points to another constant pointer which points to a constant char. Have a look at the spiral rule.

int bar;
const char* const* const* ptr = foo(bar);

So basically you cannot change any of *ptr or **ptr or ***ptr.

HelloWorld123456789
  • 5,299
  • 3
  • 23
  • 33