82

From my understanding, const modifiers should be read from right to left. From that, I get that:

const char*

is a pointer whose char elements can't be modified, but the pointer itself can, and

char const*

is a constant pointer to mutable chars.

But I get the following errors for the following code:

const char* x = new char[20];
x = new char[30];   //this works, as expected
x[0] = 'a';         //gives an error as expected

char const* y = new char[20];
y = new char[20];   //this works, although the pointer should be const (right?)
y[0] = 'a';         //this doesn't although I expect it to work

So... which one is it? Is my understanding or my compiler(VS 2005) wrong?

Puppy
  • 144,682
  • 38
  • 256
  • 465
Luchian Grigore
  • 253,575
  • 64
  • 457
  • 625

6 Answers6

133

Actually, according to the standard, const modifies the element directly to its left. The use of const at the beginning of a declaration is just a convenient mental shortcut. So the following two statements are equivalent:

char const * pointerToConstantContent1;
const char * pointerToConstantContent2;

In order to ensure the pointer itself is not modified, const should be placed after the asterisk:

char * const constantPointerToMutableContent;

To protect both the pointer and the content to which it points, use two consts.

char const * const constantPointerToConstantContent;

I've personally adopted always putting the const after the portion I intend not to modify such that I maintain consistency even when the pointer is the part I wish to keep constant.

Greyson
  • 3,598
  • 1
  • 21
  • 22
  • 24
    'convenient shorthand' is an interesting description for something which is not shorter and doesn't follow the normal rules. – beetstra Nov 11 '11 at 12:01
  • The standard doesn't really care which order you use. Section 7.1.6 just shows both places and says use it in only one. – edA-qa mort-ora-y Nov 11 '11 at 12:04
  • 1
    @beetstra I agree. I changed it to "convenient mental shortcut" to be a bit more clear. – Greyson May 03 '12 at 21:47
32

It works because both are same. May be you confused in this,

const char*  // both are same
char const*

and

char* const  // unmutable pointer to "char"

and

const char* const  // unmutable pointer to "const char"

[To remember this, here is a simple rule, '*' affects its whole LHS first]

iammilind
  • 68,093
  • 33
  • 169
  • 336
28

That is because the rule is:

RULE: const binds left, unless there is nothing on the left, then it binds right :)

so, look at these as:

(const --->> char)*
(char <<--- const)*

both same! oh, and --->> and <<--- are NOT operators, they just show what the const binds to.

Akanksh
  • 1,300
  • 8
  • 10
13

(from 2 simple variable initialization question)

A really good rule of thumb regarding const:

Read Declarations Right-to-Left.

(see Vandevoorde/Josutiss "C++ Templates: The Complete Guide")

E.g.:

int const x; // x is a constant int
const int x; // x is an int which is const

// easy. the rule becomes really useful in the following:
int const * const p; // p is const-pointer to const-int
int const &p;        // p is a reference to const-int
int * const * p;     // p is a pointer to const-pointer to int.

Ever since I follow this rule-of-thumb, I never misinterpreted such declarations again.

(: sisab retcarahc-rep a no ton ,sisab nekot-rep a no tfel-ot-thgir naem I hguohT :tidE

Community
  • 1
  • 1
Sebastian Mach
  • 38,570
  • 8
  • 95
  • 130
  • +1 This is fantastic, thank you! I've been trying to get my head around things like `const char* const` for ages and thanks to you I now get it. – OMGtechy Jul 30 '14 at 23:23
5

Here is how I always try to interpret:

char *p

     |_____ start from the asterisk. The above declaration is read as: "content of `p` is a `char`".

char * const p

     |_____ again start from the asterisk. "content of constant (since we have the `const` 
            modifier in the front) `p` is a `char`".

char const *p

           |_____ again start from the asterisk. "content of `p` is a constant `char`".

Hope it helps!

yasouser
  • 5,113
  • 2
  • 27
  • 41
0

In both of your cases you're pointing to a constant char.

const char * x  //(1) a variable pointer to a constant char
char const * x  //(2) a variable pointer to a constant char
char * const x  //(3) a constant pointer to a variable char
char const * const x //(4) a constant pointer to a constant char
char const * const * x //(5) a variable pointer to a constant pointer to a constant char
char const * const * const x //(6) can you guess this one?

By default, const applies to what is inmediately at is left, but it could apply to what is inmediately at its right if there's nothing preceeding it, as in (1).

  • Last one: A constant variable pointer, to a constant pointer, to a constant char. – Secko Feb 02 '19 at 15:20
  • If by "constant variable pointer" you mean "constant pointer", then you nailed it bro! – Lino Mediavilla Feb 03 '19 at 16:10
  • Well in (5) that's a variable pointer to a constant pointer to a constant char simply because there's no "const" to the right of the last asterisk before the identifier "x". But in (6) that becomes a constant pointer, the rest remaining the same. – Lino Mediavilla Feb 05 '19 at 00:15