What Use Are Const Pointers (As Opposed to Pointers to Const Objects)

What use are const pointers (as opposed to pointers to const objects)?

When you're designing C programs for embedded systems, or special purpose programs that need to refer to the same memory (multi-processor applications sharing memory) then you need constant pointers.

For instance, I have a 32 bit MIPs processor that has a little LCD attached to it. I have to write my LCD data to a specific port in memory, which then gets sent to the LCD controller.

I could #define that number, but then I also have to cast it as a pointer, and the C compiler doesn't have as many options when I do that.

Further, I might need it to be volatile, which can also be cast, but it's easier and clearer to use the syntax provided - a const pointer to a volatile memory location.

For PC programs, an example would be: If you design DOS VGA games (there are tutorials online which are fun to go through to learn basic low level graphics) then you need to write to the VGA memory, which might be referenced as an offset from a const pointer.

-Adam

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

constant pointer vs pointer on a constant value

char * const a;

means that the pointer is constant and immutable but the pointed data is not.

You could use const_cast(in C++) or c-style cast to cast away the constness in this case as data itself is not constant.

const char * a;

means that the pointed data cannot be written to using the pointer a.
Using a const_cast(C++) or c-style cast to cast away the constness in this case causes Undefined Behavior.

What's the point of const pointers?

const is a tool which you should use in pursuit of a very important C++ concept:

Find bugs at compile-time, rather than run-time, by getting the compiler to enforce what you mean.

Even though it doesn't change the functionality, adding const generates a compiler error when you're doing things you didn't mean to do. Imagine the following typo:

void foo(int* ptr)
{
ptr = 0;// oops, I meant *ptr = 0
}

If you use int* const, this would generate a compiler error because you're changing the value to ptr. Adding restrictions via syntax is a good thing in general. Just don't take it too far -- the example you gave is a case where most people don't bother using const.

Pointing to a const pointer (or a pointer to a const)

Your first rewrite did not work, because you tried to assign an address of a constant pointer to a pointer-to-pointer where the final "pointee" (i.e. the int) is constant, rather than the pointer in the middle. In other words, if C allowed this

int *const p1 = &v1;
const int **p2 = &p1; // Not allowed

it should allow this:

*p2 = &v2; // This would be legal.

However, this would have modified the pointer p1, which is allegedly constant.

Here is what you need to change for the first rewrite to work:

int *const p1 = &v1;
int * const *p2 = &p1;

Note how const is moved from before the declaration to between the asterisks. Now you are making a pointer to a constant pointer to int.

Your second rewrite fails because it drops const-ness altogether. To fix it, put const back at the beginning of the declaration:

const int *p1 = &v1;
const int **p2 = &p1;

const pointer vs pointer: C++

In this case there shouldn't actually be any performance gain, because the keyword const in your example only tells the compiler that the pointer access will be limited to read-only access (this could only increase performance e.g. in cases with mutex-protected or atomic pointers). But the pointer itself is going to be a variable!

If, however, you meant to use a constant pointer to a read-only value, then you would have had to declare it like this:

const DATATYPE *const name

And even in this revised case, most compilers shouldn't see any performance improvements, because good compilers automatically detect if something is actually treated as a constant and/or read-only entity in a given code and then optimize accordingly (internally) without the programmer having to bother with redundant and excessive "const embellishments" everywhere. (Not saying all const uses are redunant -- far from it, as e.g. const explicitly used to define a read-only entity makes for a good and safe API.)

this' keyword used in class and objects is a constant pointer?

According to 9.3.2 The this pointer [class.this]

1 In the body of a non-static (9.3) member function, the keyword this is a prvalue expression whose value
is the address of the object for which the function is called. [...]

So as the error says, the left hand side should be an lvalue but you're giving it a prvalue because change is a non-static member function and inside any non-static member function the keyword this is a prvalue according to the above quoted statement. Hence the error.

But you can modify the object that this points to, as shown below:

#include <iostream>
using namespace std;
class Test
{
private:
int x;
public:
Test(int x = 0) { this->x = x; }
void change(Test *t) { *this = *t; }//THIS WORKS
void print() { cout << "x = " << x << endl; }
};

int main()
{
Test obj(15);
Test *ptr = new Test (100);
obj.change(ptr);
obj.print();
return 0;
}

Note in the above example i have replaced this = t; with

*this = *t;//this time it works because now the left hand side is an lvalue 

This time the program works because now the left hand side is an lvalue.

Some More Explanation

From IBM's this pointer documentation,

The this parameter has the type Test *const. That is, it is a constant pointer to a Test object. Now since it is constant pointer, you cannot assign a different pointer value to it using this = t;. And hence the error.

Similarly, from Microsoft's this pointer documentation,

the this pointer is always a const pointer. It can't be reassigned.

So this also explains the error you're getting.

What is the difference between const int*, const int * const, and int const *?

Read it backwards (as driven by Clockwise/Spiral Rule):

  • int* - pointer to int
  • int const * - pointer to const int
  • int * const - const pointer to int
  • int const * const - const pointer to const int

Now the first const can be on either side of the type so:

  • const int * == int const *
  • const int * const == int const * const

If you want to go really crazy you can do things like this:

  • int ** - pointer to pointer to int
  • int ** const - a const pointer to a pointer to an int
  • int * const * - a pointer to a const pointer to an int
  • int const ** - a pointer to a pointer to a const int
  • int * const * const - a const pointer to a const pointer to an int
  • ...

And to make sure we are clear on the meaning of const:

int a = 5, b = 10, c = 15;

const int* foo; // pointer to constant int.
foo = &a; // assignment to where foo points to.

/* dummy statement*/
*foo = 6; // the value of a can´t get changed through the pointer.

foo = &b; // the pointer foo can be changed.

int *const bar = &c; // constant pointer to int
// note, you actually need to set the pointer
// here because you can't change it later ;)

*bar = 16; // the value of c can be changed through the pointer.

/* dummy statement*/
bar = &a; // not possible because bar is a constant pointer.

foo is a variable pointer to a constant integer. This lets you change what you point to but not the value that you point to. Most often this is seen with C-style strings where you have a pointer to a const char. You may change which string you point to but you can't change the content of these strings. This is important when the string itself is in the data segment of a program and shouldn't be changed.

bar is a constant or fixed pointer to a value that can be changed. This is like a reference without the extra syntactic sugar. Because of this fact, usually you would use a reference where you would use a T* const pointer unless you need to allow NULL pointers.

C++ Const pointer declaration

It means "myPtr is a const pointer to a const myClass". It means that you can neither modify what the pointer is pointing at through this pointer nor can you make the pointer point somewhere else after it's initialised (by the return value of myClass->getPointer()). So yes, you're basically right, with the addition that it also points to a const object (as far as you know; it could really be non-const underneath).

Remember that const applies to the item to its left (or if there is no item to its left, the item to its right). The first const makes the myClass const (where you can't modify what the pointer points at) and the second const makes the * const (where you can't modify the pointer itself).



Related Topics



Leave a reply



Submit