3

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 enter image description here

Forgive my ignorance but, aren't they suppose to mean the same thing ?

Community
  • 1
  • 1
Tasdik Rahman
  • 2,160
  • 1
  • 25
  • 37
  • http://c-faq.com/decl/spiral.anderson.html – chris Oct 05 '14 at 07:11
  • 1
    Personally I dislike the *spiral* approach to reading types, I would recommend that you place `const` in the *right* (correct) place, which is to the *right* (as opposed to *left*) of the type being `const`, in the code above: `int const *` and `int * const`. Then read from right to left. – David Rodríguez - dribeas Oct 05 '14 at 09:17
  • @chris: Spiral Rule is WRONG. Listen to David Rodriguez – kotlomoy Oct 05 '14 at 16:32
  • @kotlomoy, The spiral rule has not once failed me in reading a type. The only exception is really this cv qualifier being allowed to go on the left. If I could rename it, I'd prefer something like the Alternating Right-Left Rule, but once you understand the technique, you'll be hard-pressed to find something you can't read. – chris Oct 05 '14 at 17:18
  • @chris: "you'll be hard-pressed to find something you can't read." - `int a[2][3]`. For info: I wasn't pressed at all – kotlomoy Oct 05 '14 at 20:31

5 Answers5

2

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.

Javi
  • 3,440
  • 5
  • 29
  • 43
2
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

P0W
  • 46,614
  • 9
  • 72
  • 119
1
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
Dr. Debasish Jana
  • 6,980
  • 4
  • 30
  • 69
1

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
Community
  • 1
  • 1
WhozCraig
  • 65,258
  • 11
  • 75
  • 141
0

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.

dgnuff
  • 3,195
  • 2
  • 18
  • 32