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