Reputation: 2330
I am learning about constant pointers and I was trying this
#include<iostream>
using namespace std ;
int main(){
int a = 10 ;
const int *cp = &a ; // my constant pointer variable
cout<<"\nAddress stored in cp = "<<cp ;
++cp;
cout<<"\nAddress stored in cp = "<<cp ;
}
It incremented the address which was stored in cp
But according to what I have understood until now, shouldn't ++cp
give an error as it is a constant pointer that always points to the same address and this address cannot be modified.
But when I replaced
const int *cp = &a ;
with int *const cp = &a ;
It gives me this
Forgive my ignorance but, aren't they suppose to mean the same thing ?
Upvotes: 3
Views: 968
Reputation: 3557
This is one of the reasons I always recommend placing the const
on the right of the int
not the left. As in:
int const *cp;
and not:
const int *cp;
That has the advantage that the item that is made const
is what's on the right of the const
keyword, and it's type is on the left.
In the above, *cp (i.e. the contents of cp) is const, and it's type is int. If you write
int * const cp = &foo;
and apply the same rules, cp
is const
and the const
item has type int *
. When there are multiple levels of indirection, using this rule makes it far easier to understand what's happening.
int const ** cpp1;
int * const *cpp2;
int ** const cpp3 = &bar;
int const ** const cpp4 = &xyz;
That last one is a const
pointer to a mutable pointer to a const int
. And one const
item has type int
while the other has type int **
. Trivial to understand, as long as you never place the word const
on the left of the int
.
Upvotes: 0
Reputation: 66194
If it helps at all (and it probably doesn't), the following are synonymous, taking advantage of a language nicety that allows an opening type to have const
appear on the immediate left or right of the type, but before any additional qualifiers (like pointers or references):
const int * p; // does NOT require initialization
int const * q; // same as above
Both declare pointers to constant int
data, and are interchangeable in syntax.
Whereas this:
int * const p = &a; // requires initialization.
declares a constant pointer to int
data; not a pointer to constant int
data.
Extending this further (actually merging them both), we get:
const int * const p = &a;
int const * const p = &a;
These are synonymous. Both declare a constant pointer to constant int data. Neither the pointer, nor what it points to are modifiable, and both require initialization.
Shamelessly Ripped Off Chart
The following was shamelessly ripped off from.. myself (ok, not that much shame), from a slightly related question. I hope it helps further explain the differences in what happens when you position const
and *
in different places of a declaration:
Single-Indirection:
char *p; // p is mutable, *p is mutable
const char *p; // p is mutable, *p is const
char const *p; // same as above.
char *const p; // p is const, *p is mutable, must be initialized.
char const *const p; // p is const, *p is const, must be initialized.
Double Indirection:
char **p; // ptr-to-ptr-to-char
// p, *p, and **p are ALL mutable
const char **p; // ptr-to-ptr-to-const-char
// p and *p are mutable, **p is const
char const **p; // same as above
char *const *p; // ptr-to-const-ptr-to-char
// p is mutable, *p is const, **p is mutable.
char **const p; // const-ptr-to-ptr-to-char
// p is const, *p is mutable, **p is mutable.
// must be initialized.
const char **const p; // const-ptr-to-ptr-to-const-char
// p is const, *p is mutable, **p is const.
// must be initialized.
char const **const p; // same as above
char const *const *p; // ptr-to-const-ptr-to-const-char
// p is mutable, *p is const, **p is const.
const char *const *p; // same as above.
char *const *const p; // const-ptr-to-const-ptr-to-char
// p is const, *p is const, **p is mutable.
// must be initialized.
And my personal favorite:
char const *const *const p; // const-ptr-to-const-ptr-to-const-char
// everything is const.
// must be initialized.
const char *const *const p; // same as above
Upvotes: 1
Reputation: 47784
const int *cp = &a ;
Content of address pointed by cp
is read-only, however pointer cp
is not
So,
*cp = value ; //Illegal
++cp ; // Legal
int *const cp = &a ;
Pointer is read-only, however content of address pointed by cp
is not
So,
*cp = value ; //Legal
++cp ; // Illegal
Also,
const int *const cp = &a ;
Both pointer as well as content of address pointed by cp
are read-only
*cp = value ; //Illegal
++cp ; // Illegal
For simple declaration read from right to left
Upvotes: 2
Reputation: 7118
const int *cp1 = &a ; // pointer is variable, pointed to is constant
int *const cp2 = &a ; // pointer is constant, pointed to is variable
const int *const cp3 = &a ; // pointer is constant, pointed to is constant
Thus,
cp1++; // possible
*cp1++; // not possible
cp2++; // not possible
*cp2++; // possible
cp3++; // not possible
*cp3++; // not possible
Upvotes: 1
Reputation: 3610
When you are doing int *const cp = &a;
it means a integer pointer to a constant cp, so cp cannot change. However, in your previous version const int *cp
means a constant int pointer to cp, so the value where cp points cannot change, but the pointer itself can.
Usually, people like to read this from right to left:
const int *cp
cp is a pointer to a int constant, so the integer number cannot change.
int *const cp = &a;
cp is a constant pointer to an int, so the pointer cannot change.
Upvotes: 2