Published on

C++ Pointer basics

Authors
  • avatar
    Name
    Abid Zaidi
    Twitter

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.