The use of const with a pointer can make the pointee not modifiable by dereferencing it using the pointer in question. But why neither can I modify what the pointer is not direc
The non-modifiability introduced by const
depends on where const
is written.
If you write
const int * ptr = &a;
(or int const * ptr = &a;
), the const
refers to the pointee, so using the pointer for writing to the destination is forbidden.
(OTOH, if wou wrote
int * const ptr = &a;
you couldn't modify ptr
.)
In your case, everything involving writing to the destination is forbidden.
This includes *ptr
and ptr[0]
(which are equivalent), but also everything involving a modification of the destination address, such as *(ptr + 2)
or ptr[2]
.
Let's think about the type of the expressions.
const int* ptr = &a;
The type of ptr
is const int*
.
So the type of *ptr
is const int
. Not modifiable.
The type of (ptr + 2)
is still const int*
so the type of *(ptr + 2)
is const int
which is again not modifiable.
Although other answers explain the technicalities of why it doesn't work, I'd like to offer a more general reason: it's the only thing that makes sense.
The problem is that there is no general way for the compiler to decide whether p + something
is the same as p
or not, because something
can be arbitrarily complex. A rule like "Values pointed to by p
and p + 0
are unmodifiable, but other values can still be modified" cannot be checked at compile time: imagine if you wrote:
*(p + very complex expression) = ...
should your compiler be able to figure out if very complex expression
is zero? What about
int s;
scanf("%d", &s);
*(p + s) = ...
What should the compiler do in that case?
The only reasonable choice here was to make any value accessed through p
unmodifiable.
Since a pointer can also be used as an array (think about argv
), the compiler restricts each access in which the pointer is involved. This way the whole array is read-only.
ptr +2
simply has the same type as ptr
namely is a pointer to a const
object.
Pointer arithmetic supposes that the object that is pointed to is an array of all the same base type. This type includes the const
qualification.