Const int pointer error
I am learning about persistent pointers and I tried to do 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 that was stored in cp
But according to what I have understood so far, one should not ++cp
give an error as it is a persistent pointer that always points to the same address and this address cannot be changed.
But when I replaced
const int *cp = &a ;
from int *const cp = &a ;
It gives me this
Forgive my ignorance, but don't they mean the same thing?
source to share
When you execute int *const cp = &a;
it means an integer pointer to the constant cp, so cp cannot change. However, in your previous version const int *cp
means a constant int pointer to cp, so a value where the 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 constant int, so the integer cannot change.
int *const cp = &a;
cp is a constant pointer to int, so the pointer cannot change.
source to share
const int *cp = &a ;
The content of the address it points cp
to is read-only, but the pointer is cp
not
So,
*cp = value ; //Illegal
++cp ; // Legal
int *const cp = &a ;
The pointer is read-only, but the content of the address it points to cp
is not
So,
*cp = value ; //Legal
++cp ; // Illegal
Besides,
const int *const cp = &a ;
Both pointers, as well as the address of the address they point to cp
, are read-only
*cp = value ; //Illegal
++cp ; // Illegal
For a simple right-to-left readable ad
source to share
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
source to share
If it helps at all (and it probably doesn't), the following synonyms, taking advantage of the language, which allows the type to const
be exposed to appear on the immediate left or right side of the type, but before any additional qualifiers (such as pointers or references):
const int * p; // does NOT require initialization
int const * q; // same as above
Both declare pointers to constant data int
and are used interchangeably in syntax.
Whereas this:
int * const p = &a; // requires initialization.
declares a persistent pointer to data int
; not a pointer to persistent data int
.
Continuing this (effectively combining both of them), we get:
const int * const p = &a;
int const * const p = &a;
These are synonyms. Both declare a constant pointer to constant int data. Neither the pointer nor what it points to is modifiable, and both require initialization.
Shamelessly torn chart
The following was shamelessly ripped off of myself (well, not much shame), from a slightly related question . Hopefully this will help explain even more the differences in what happens when you position const
and *
in different places of the ad:
Single-Indirect :
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
source to share
This is one of the reasons I always recommend placing to the const
right of int
not to the left. How in:
int const *cp;
and not:
const int *cp;
This has the advantage that the element created const
is the one to the right of the keyword const
and it's to the left.
In the above example, * cp (i.e. the content of cp) is const and the type is int. If you write
int * const cp = &foo;
and apply the same rules, cp
there is const
, and the element const
is of type int *
. When there are multiple levels of indirection, using this rule makes it much easier to understand what's going on.
int const ** cpp1;
int * const *cpp2;
int ** const cpp3 = &bar;
int const ** const cpp4 = &xyz;
This latter is a const
pointer to a mutable pointer to const int
. And one element const
is of type int
and the other is of type int **
. It's trivial to understand if you never put a word to the const
left of int
.
source to share