Reputation: 535
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;
Upvotes: 4
Views: 996
Reputation: 78903
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.
Upvotes: 1
Reputation: 123458
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
Upvotes: 3
Reputation: 215183
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).
Upvotes: 0
Reputation: 26060
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)].
Upvotes: 9
Reputation: 20616
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.
Upvotes: 0
Reputation: 14558
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.
Upvotes: 1