- Published on
C++ Pointer basics
- Authors
- Name
- Abid Zaidi
Understanding pointers
Pointers are variables that store memory addresses to a value. Usually variables occupy more than one addresses. Since each memory address is of one byte so lets say we use an object of 2 bytes the variable uses two blocks of memory address. Memory addresses are a series of contiguous blocks and the position of a variable in memory is decided by the system on runtime. So if a value of a pointer is edited during the life cycle of the program the pointer would reflect it and thats the biggest advantage of using pointers. The hardest part of using a pointer is that its upto the developer to keep track of all pointers, to avoid accessing an invalid pointer or a memory leak.
In C++, A pointer can be create in the following ways
- Using the *
- new keyword
- smart pointers
Inorder to get the value from a pointer we can use the Dereference operator '*' which gives us the value pointed by the pointer. For reading the memory address of a value we can use the Address-of operator '&' which will return the memory address of that value. This memory address can be used in assigning a value to the pointer.
Different ways to create and access a pointer
int a = 10; // value
int *b = &a; // Using the Address-of operator
int c = *b; // Dereference a pointer
int *d; // Create a pointer
*d = a; // Assign a value to the pointer
cout << a << endl; // prints: 10
cout << b << endl; // prints: 0x16d23314c
cout << *b << endl; // prints: 10
cout << c << endl; // prints: 10
cout << *d << endl; // prints: 10
Pointers with const
Pointers can be secured when with 'const', advantage of using it ensures that the value of the pointer cannot be edited. One of common use case of using const pointers is in function parameters where you don't want other methods to overwrite the value of the pointer
In the below example, x and z are values and y is a const pointer. You can only read from y but you can never edit the value of y.
int x = 15;
const int *y = &x;
int z = 0;
z = *y;
*y = 99; // Invalid, wouldn't compile since y is only readable
To add a little more complexity, in the above example our value is const but the pointer itself is not. If you want the pointer itself to be const as well, meaning you can't change the address it points to then add 'const' after the type
int v1 = 10;
int v2 = 10;
const int * p1 = &v1;
const int *const p2 = &v2;
p1 = p2;
p2 = p1; // Invalid, wouldn't compile since y is only readable
Void pointers
Used in cases where the type of pointer is not known, which means it points to a location whose type is identified on runtime. This gives a lot of flexibility as you can assign int, float, string etc to it. This opens a limitation, you can only dereference it with a type cast which makes sense since the type is not known.
int voidValue = 25;
void *voidPointer = &voidValue;
int *intPointer;
intPointer = (int *)voidPointer;
cout << *intPointer << endl;
Invalid pointers
Pointers can be null on initializing or during the course of the program, when these pointers are dereferenced they throw a segmentation fault. Following is a quick example on it
int *x0 = nullptr;
cout << *x0 << endl; // Throws a segmentation fault during execution
In order to tackle situation like these we simply add a check to see if the pointer is valid.
if(x0 != nullptr) // or to be concise if(!x0)
cout << "<Your code goes here>" << endl;
To conclude there is a lot more to pointers but for now I've covered the basics of it. I'll add more blogs covering topics such as Pointers with array/strings, Pointer arithmetics and also advanced topics such as Smart Pointers later on.