Const Pointer Assign to a Pointer

const pointer assign to a pointer

There is difference between constant pointer and pointer to constant. Constant pointer is a pointer (a number - memory address) that cannot be changed - it always point to the same object given via initialization:

int * const const_pointer = &some_int_var; // will be always pointing to this var
const_pointer = &some_other_var; // illegal - cannot change the pointer
*const_pointer = 2; // legal, the pointer is a pointer to non-const

Pointer to constant is a pointer whose pointed value cannot be changed:

const int * pointer_to_const = &some_int_var; // doesn't have to be always pointing to this var
pointer = &some_other_var; // legal, it's not a constant pointer and we can change it
*pointer = 2; // illegal, pointed value cannot be changed

You can always assign constant to variable i.e. const pointer to non-const pointer (a). You can cast pointer to non-const to a pointer to const (b). But you cannot cast pointer to const to a pointer to non-const (c):

int * pointer;
int * const const_pointer = &var;
const int * pointer_to_const;

/* a */
pointer = const_pointer; // OK, no cast (same type)

/* b */
pointer_to_const = pointer; // OK, casting 'int*' to 'const int*'

/* c */
pointer = pointer_to_const; // Illegal, casting 'const int*' to 'int*'

[EDIT] Below, this is not standard c++. However, this is common.[/EDIT]

String literal

"Hello"

is converted to constant pointer to const (const char * const):

char *pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
char * const const_pointer = "Hello"; // Illegal, cannot cast 'const char*' to 'char*'
const char * pointer_to_const = "Hello"; // OK, we can assign a constant to a variable of the same type (and the type is 'const char*')
"Hello" = pointer_to_const; // Illegal cannot re-assign a constant

In above examples the second is your case. You tried to initialize pointer-to-non-const with a pointer-to-const when passing string literal as argument of your function. No matter if these pointers are constants or not, it's matter what do they point to.

Summary:

1) If you cast a pointer of some type to a pointer of another type, you cannot cast pointer-to-const to pointer-to-non-const.

2) If you have constant pointer, the same rules applies as to other constants - you can assign a constant to a variable but you cannot assign a variable to a constant (except initializing it).

// EDIT

As GMan pointed out, the C++98 standard (§4.2/2) allows to implicitly cast string literals (which are constant char arrays) to a non-const char pointer. This is because of backward compatibility (in C language there are no constants).

Of course such a conversion can lead to mistakes and compilers will violate the rule and show an error. However, GCC in compatibility mode shows only a warning.

conversion from const pointer to pointer

Your addPoint() takes a non-const pointer:

void Polygon::addPoint(Point* p) {

But you're trying to pass it a const Point*, hence the error. The compiler doesn't know that you end up not modifying what p points to - so it could be a violation of const to let you do what you're trying to do.

For instance, if addPoint() did:

void Polygon::addPoint(Point* p) { p->setX(42); }

It would be clearly wrong to let you pass a const Point* in.

However, since you don't actually need p to point to a non-const Point you can just change the signature to reflex this:

void Polygon::addPoint(const Point* p) {

Const pointer pointing to non-const data

In this case, there is a type mismatch

No; there is no type mismatch in this case. It is a pointer to non-cost and you initialise it with a pointer to non-const.

Alternatively, if you insist on there being a "mismatch", then it is analogous to the following "mismatch":

const int b = 42;

Why is the second case valid

Simply put: The constness of the initialiser is irrelevant to whether it initialises a const object or not. Besides, the initialiser is a prvalue of a non-class type so const qualification doesn't even apply to it.

C++ - can't assign top-const pointer to another non-const pointer

Emm... Declared type of p1 is int *. And type of p2 in const int *.
So you want to assign const int* to int*, which isn't allowed.
p1 = &var is allowed, because var has int type, not const int.

assigning a pointer to const to a pointer

A pointer to const is about privileges, not the fundamental type of the pointed-to object.

Essentially, with an int const * (which is the same as const int*), you can look at the int (which may or may not be const itself), but you can't change it. Casting a non-const pointer to a const one allows you to pass a pointer to your own data to a function and not worry that the function might modify it, even though you still can.

To preserve the above dynamic, you can't "get rid" of constness by assigning to another pointer.* That's what your error is saying. That is,

const int * constPtr;
int * nonconstPtr;

*nonconstPtr = 42; // legal
constPtr = nonconstPtr; // legal

*constPtr = 42; // illegal!
nonconstPtr = constPtr; // illegal!

* You actually can cast away constness with const_cast<>. And there are correct uses of the operation. But it is usually very wrong, and you should very probably avoid it.

Why can't I assign value of pointer to const int to a pointer of int?

First consider this example:

void foo(const int* p) {
*x = 1; // Error ! x is pointer to const
}

int x = 42;
foo(&x);

x is not const. Nevertheless, inside foo you are not allowed to modify its value via the const int* p, because it is a pointer to a const int. Having a pointer to const int does not imply that the int pointed to is actually const. It only means: You are not allowed to modify the int via that pointer.

The compiler does not consider what pointer you actually pass to see that *x = 1; is not allowed inside foo.

An int * on the other hand, does allow to modify the pointed to int. Now consider this:

 const int x = 42;
const int* p = &x;

int* p2 = p; // Error ! why?
*p2 = 0; // <- because of this

If you were allowed to assign the const int* to a int* this would create a hole in const correctness, because a int* does allow you to modify the pointee.

The top level const in

 const int* const p3 = &x;

refers to the pointer itself. You cannot modify the pointer. While you can modify this one:

 const int* p4;
p4 = &x;

Const pointer to a non-const variable

You told the compiler "I am not going to try assigning to *p" (that is really all there is to const), but that says nothing about i.

#include <stdio.h>
void main(void) {
int i = 1;
const int *p = &i;
printf("i=%d\np*=%d\n", i, p);
i = 5;
printf("i=%d\np*=%d\n", i, p);
*p = 10;
printf("i=%d\np*=%d\n", i, p);
}

GCC will complain about assignment of read-only location '*p', but i=5 is fine, since i is not const. Remove the const from *p, or remove the assignment *p=10, and everything is good.

If the reference to i were to somehow disappear, then that memory space would effectively become read-only from the programmer's perspective: the compiler won't let me write to *p, and that is the only handle I have left for that piece of memory.

Constant pointer vs Pointer to constant

const int* ptr; 

declares ptr a pointer to const int type. You can modify ptr itself but the object pointed to by ptr shall not be modified.

const int a = 10;
const int* ptr = &a;
*ptr = 5; // wrong
ptr++; // right

While

int * const ptr;  

declares ptr a const pointer to int type. You are not allowed to modify ptr but the object pointed to by ptr can be modified.

int a = 10;
int *const ptr = &a;
*ptr = 5; // right
ptr++; // wrong

Generally I would prefer the declaration like this which make it easy to read and understand (read from right to left):

int const  *ptr; // ptr is a pointer to constant int 
int *const ptr; // ptr is a constant pointer to int


Related Topics



Leave a reply



Submit