8

In running this C++ code, I expected the output to be Abc, but, it was FFF, why is that? Isn't name pointing to a constant char?

#include <iostream>
int main()
{
    const char* name = "Abc";
    name = "FFF";
    std::cout<<name<<std::endl;
    return 0;
}
Mateen Ulhaq
  • 24,552
  • 19
  • 101
  • 135
Simplicity
  • 47,404
  • 98
  • 256
  • 385
  • I advise you to read this post about [const](http://stackoverflow.com/questions/1143262/what-is-the-difference-between-const-int-const-int-const-int-const) – canardman Jan 28 '11 at 11:09

9 Answers9

14

Yes, it's pointing to a const char as you say, but it is not a constant pointer. You are changing what you are pointing to, not the contents of what you are pointing to. In other words, the memory holding "Abc" still holds the characters "Abc" after you reassign the pointer.

For a constant pointer, you want const char* const name = "Abc";. In this case, it won't compile since you can't change what the pointer points to.

In general, with const and pointers in C++, you can read the type name from right-to-left to get a feel for what is going on. For example, in the const char* const case, you can read this as "a constant pointer to a character constant". A little weird, but it works.

Chris Schmich
  • 29,128
  • 5
  • 77
  • 94
6

const char* name = "Abc"; -> Non const pointer-> name, but data (Abc) is constant

name = "FFF" -> changing pointer(name) to point to FFF.

char *p              = "Hello";          // non-const pointer,
                                         // non-const data
const char *p        = "Hello";          // non-const pointer,
                                         // const data
char * const p       = "Hello";          // const pointer,
                                         // non-const data
const char * const p = "Hello";          // const pointer,
                                         // const data
DumbCoder
  • 5,696
  • 3
  • 29
  • 40
  • 1
    This is (one reason. The other being the typdef rule) why I prefer to always put the const on the right. It makes this rule easier to parse. `char const * const p`. Read right to left: `p is a "constant *" to "constant char"` – Martin York Jan 28 '11 at 11:26
  • For some reason, I never had any issues reading `const char*` properly. It always naturally felt that `const` belongs to `char`. – Mephane Jan 28 '11 at 13:04
  • 1
    @Mephane: Sure. But now stick a typedef in there and see what the meaning becomes (if you are not careful it changes (when const is first)) but is consistent when const is placed on the left of the object. – Martin York Jan 28 '11 at 18:56
  • I know. That's why I don't typedef pointers unless absolutely unavoidable (a situation I have yet to encounter). The problem with typedefs on pointers is that you can only make the pointer value const using the alias created by the typedef, you need a seperate typedef for a pointer-to-const. I prefer just using the C++ keywords instead. – Mephane Jan 31 '11 at 10:47
3

With const char* name = "Abc"; you are telling compiler you will not change the contents of "Abc" using name. However, you are free to change the pointer to point to a different memory location. See this FAQ for details.

Naveen
  • 74,600
  • 47
  • 176
  • 233
3

It is a known issue with const and English speakers.

The syntax allows both:

  • const T
  • T const

and both have the same meaning.

However it becomes complicated once you throw a pointer in the mix:

  • const T* should be read (const T)*
  • T const* should be read (T const)*
  • T* const should be read (T*) const

For that reason I am an adept of always using const on the immediate right of the object. This is more consistent.

Note that the same issue can be found with typedef, let's define typedef T* pointer:

  • const pointer means T* const, not const T* (as a macro would imply)
  • pointer const means T* const, like the textual replacement

If you take the habit of putting the const after the name, and not before like an adjective in English, then you won't fall into those traps.

Matthieu M.
  • 287,565
  • 48
  • 449
  • 722
2

in deed the most correct syntax is

char const * pName;

because const keyword apply namely to the part on the left hand side.

if you want a const poitner to a const char you would write it:

char const * const pName;

and a const pointer to an int;

int * const pInt;

PS: but I still write the const at the begining of the line whenever I can, an anchored habbit ;-)

Stephane Rolland
  • 38,876
  • 35
  • 121
  • 169
0
const char* name = "Abc";

Actually this means, name is a pointer to the const data. Means, it's the data which is const, not the pointer itself. So it's perfectly valid if you write:

name = "FFF"; //ok : changing the pointer

However, the following will not compile:

 char * const name = "Abc"; //const pointer to the non-const data!
 name = "FFF"; //error: trying to change the pointer itself!

See the compiler error:

prog.cpp:5: error: assignment of read-only variable ‘name’

See yourself here : http://www.ideone.com/KyNXx

Nawaz
  • 353,942
  • 115
  • 666
  • 851
0

When you declare a variable as

const T* ptr = /*...*/

You are declaring a pointer saying that the object being pointed at, not the pointer, must not change. In other words, it's a "pointer to a T that's const."

If you want to make it impossible to reassign the pointer, you can write

T* const ptr = /*...*/

This is now an immutable pointer to a T, which can be modified.

You can combine these together like this:

const T* const ptr = /*...*/

To get an immutable pointer to an immutable T.

As a fun hint, you can usually determine what parts of a pointer/pointed pair can be modified by reading the type right-to-left. Try that out on the above and see what you get.

templatetypedef
  • 362,284
  • 104
  • 897
  • 1,065
0

First, const is only checked at compilation time. If it compiles, all operations will be done normally at runtime.

In your example, const applies to the content pointed by name. So you are allowed to change the pointer, but not the content.

strcpy(name, "FFF");

would be refused, but not changing the pointer like you did.

Benoit Thiery
  • 6,325
  • 4
  • 22
  • 28
0

The literal strings "Abc" and "FFF" are constant, but name is a variable (pointer to constant data). You have simply changed the variable to point to different constant data.

Moreover while in this case the data was necessarily constant, a pointer to constant data only means that the data cannot be modified by dereferencing that pointer, the data might also be modified directly or through a different pointer. E.g.

int i = 0 ;
const int* p = &i ;
i++ ; // valid
(*p)++ // error.
Clifford
  • 88,407
  • 13
  • 85
  • 165