4

I'm having a bit trouble deducing what is const, when applied to pointers to pointers, etc. i.e., what is const when you have

 const Foo **foo;

Can I here change something in **foo ? as in foo[0]->bar = 12;

What about:

 const Foo ***foo;
 Foo **const foo;
Anonym
  • 525
  • 2
  • 6
  • 12

6 Answers6

9

You could use cdecl to understand what a C declaration means.

const int **foo;
declare foo as pointer to pointer to const int

thus you can change pointers, but not the value they're pointing to.

int * const * const foo;
declare foo as const pointer to const pointer to int

this, instead, is a cosnt pointer, pointing to a const pointer, to a non-const int: you cannot change pointed value, but it can be changed.


C uses the Clockwise/Spiral Rule, in a case where you have only modifiers at the left side of the variable (of foo) you read stuff going from right to left:

int(5) *(4) const(3) *(2) const(1) foo;

foo is a constant(1) pointer(2) to constant(3) pointer(4) to an integer(5).

int(6) const(5) *(4) const(3) *(2) const(1) foo;
const(6) int(5) *(4) const(3) *(2) const(1) foo; // [same as above]

In this case foo is a constant(1) pointer(2) to constant(3) pointer(4) to a constant(5) integer(6) [or to an integer(5) which is constant(6)].

peoro
  • 25,562
  • 20
  • 98
  • 150
3

The const applies to the expression **foo; thus, foo and *foo are writable, but **foo is not.

Some other examples:

const Foo * const *foo;  // foo is writable, *foo and **foo are not
Foo * const * foo;       // foo and **foo are writable, *foo is not
Foo * const * const foo; // **foo is writable, foo and *foo are not
const Foo * const * const foo; // none of the expressions are writable
John Bode
  • 119,563
  • 19
  • 122
  • 198
1

const Foo * * foo (or Foo const * * foo) is a pointer to a pointer to a const Foo.

Foo * const * foo is a pointer to a const pointer to a Foo.

Foo * * const foo is a const pointer to a pointer to a Foo.

Jens Ayton
  • 14,532
  • 3
  • 33
  • 47
1

The easiest way to write such type expressions, I think, is to have the const always apply to the left. The one you gave can also be written:

Foo const**foo;

Here the const only applies to what is left, thus Foo.

Foo *const* foo;

Here on the left is Foo*

Foo const*const* foo;

is then ((Foo const)*const)*.

When you in turn want to read such an expression, interchange the const and the bare type if necessary to have the const on the right.

Jens Gustedt
  • 76,821
  • 6
  • 102
  • 177
  • This is how I write my code, const is always on the right. `Foo const foo`. `Foo const *foo`. `Foo *const foo`. – Matt Joiner Nov 23 '10 at 03:35
0

In const Foo **foo, it's the actual Foo object which is const. So you can change foo, and you can change *foo, but you can't change **foo.

For const Foo ***foo, you can change foo, *foo and **foo, but not ***foo.

For Foo **const foo, you can change *foo and **foo, but not foo itself.

Stuart Golodetz
  • 20,238
  • 4
  • 51
  • 80
0

Read types from the inside out. Starting from foo, const Foo **foo; reads * (pointer) to a * (pointer) to const Foo (a Foo object you're not allowed to modify). Foo **const foo; reads const (non-modifiable) * (pointer) to * (pointer) to Foo (a Foo object).

R.. GitHub STOP HELPING ICE
  • 208,859
  • 35
  • 376
  • 711